Skip to content

[AgentProfile] Epic: first-class Agent Profiles (named launch setups) across SDK, agent-server, canvas, cloud #3713

@simonrosenberg

Description

@simonrosenberg

Goal

Ship Agent Profiles: a library of named, reusable agent setups so a user can save everything about how an agent runs — which agent (built-in OpenHands/CodeAct vs. an ACP CLI: Claude Code / Codex / Gemini), the model + credentials, MCP servers, skills, and personality — then pick one to start a conversation. Easy UX is the product goal: Settings → Agents becomes a profile library; you launch with a profile and, where it's safe, switch the model live.

This epic tracks the implementation. It is local-first, cloud-ready: build on the SDK agent-server + agent-canvas first, with the cloud/SaaS surface following the same contract.

Status (2026-06-17)

Phase 0 ✅ · Phase 1 ✅ COMPLETE#3715 (PR #3757), #3716 (PR #3775), #3717 (PR #3780) all merged; Skill secret-masking prerequisite #3774 merged. Phases 1–3 ✅ COMPLETE. SDK v1.29.0 released (#3787, 2026-06-18) — agent-server backend now has /api/agent-profiles. One gate remains before canvas: cut a ts-client release#213 is on ts-client main but unreleased (latest v1.25.0), and canvas pins it by npm version (1.25.0). Once ts-client ships, canvas #3726 (Phase 4 centerpiece) unblocks → then #3727/#3728 → cloud #3730. Downstream of 1.29.0: watch for the OpenHands app-server + openhands-cli SDK bumps (needed for cloud #3730).

Canonical design

#3710 — "Agent Profiles: reference composition with profile-local secrets" is the design of record (it supersedes #3708 value-composition and the closed #3709), with author amendments folded in. Non-negotiable invariants every sub-issue must honor:

  • Two name-addressed profile types. LLMProfile (exists) · AgentProfile (new, kind-discriminated openhands | acp). OpenHands variant references one llm_profile_ref + 0+ server names via mcp_server_refs; ACP variant has acp_* config fields + 0+ server names via mcp_server_refs and no llm_profile_ref. The AgentProfile itself stores no secrets.
  • mcp_server_refs: list[str] | None — filter, not a separate store. Names servers in the user's existing global mcp_config.mcpServers (already a named dict). null = use all configured servers; non-null = filter to exactly those named keys. Checked at resolve-time; dangling name → hard error. SSE/shttp servers get a user-given name field in the canvas editor ([AgentProfile][canvas] AgentProfile library + kind-aware editor (dissolve ACP nav lockout) #3726) so they become referenceable.
  • Single FK lifecycle: llm_profile_ref only. Delete of a referenced LLM profile → 409 naming referrers; rename → cascade-update refs under lock; dangling ref → hard error. MCP server refs are names in the user's mutable global mcp_config — checked at resolve-time only.
  • Secrets stay out of the generic global panel. LLMProfile embeds its own secrets encrypted in-file. ACP provider creds are not stored on a profile — derived from acp_server via ACP_PROVIDERS registry and ride the single consolidated channel state.secret_registryrequest.secrets (Fix error in 422 logs due to blank bearer token #1022/Fix Laminar span stack warning in LocalConversation #1039). ACP profiles are secret-free / portable at rest.
  • resolve_agent_profile(profile, *, llm_store, mcp_config, cipher) → AgentSettingsConfig is the only join point. The existing create_agent / apply_agent_settings_diff / validate_agent_settings execution path is unchanged.
  • Creation-time only. No whole-profile mid-conversation switch. Runtime mutation stays narrow: OpenHands via switch_llm/switch_profile; ACP via session/set_model when supports_runtime_model_switch.
  • active_agent_profile_id is a NEW field — do not reuse/generalize active_profile (= active LLM profile).
  • Conservative migration. Seed exactly one default AgentProfile lazily (first GET /api/agent-profiles on empty store) — not one per existing LLM profile.

Phase 0 — Foundation (DONE ✅)

Sub-issues

Built bottom-up. = depends on.

Phase 1 — SDK substrate (software-agent-sdk)

Phase 2 — SDK agent-server (software-agent-sdk / openhands-agent-server)

Release gate (next SDK action): cut 1.29.0 via the Prepare Release workflow. It freezes + publishes the surface and unblocks downstream consumption (OpenHands app-server bump, ts-client/canvas). ⚠️ The deprecation-deadline gate forces deleting the 7 expired removed_in=1.29.0 shims (acp_env on ACPAgentSettings/ACPAgent; _return_metrics on LLM.completion/acompletion/responses/aresponses; return_metrics on RouterLLM.completion) in the rel-1.29.0 PR (the version bump makes the removal due; doing it earlier trips the API-breakage gate).

Phase 3 — typescript-client (typescript-client)

Phase 4 — agent-canvas UX (agent-canvas)

Phase 5 — OpenHands cloud / SaaS (OpenHands) — later milestone, own design pass needed

Critical path: #3715#3720#3722 (ts-client)merge rel-1.29.0 #3787 + cut ts-client release#3726 (canvas)#3727/#3728#3730 (cloud)

Repos

All sub-issues are tracked here in software-agent-sdk for unified epic tracking; each title is tagged with its target repo ([sdk], [agent-server], [ts-client], [canvas], [cloud] → OpenHands). Phase 1 substrate (#3715, #3716) landed on main 2026-06-17.

Metadata

Metadata

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions