From 071d6a8f1bfa23eed0004904c44007f440111d18 Mon Sep 17 00:00:00 2001 From: Debug Agent Date: Tue, 14 Jul 2026 19:09:23 +0200 Subject: [PATCH 1/2] docs(sdk): explain agent profile launch composition --- docs.json | 1 + sdk/arch/agent-profiles.mdx | 149 ++++++++++++++++++++++++++++++++++++ sdk/arch/overview.mdx | 1 + sdk/arch/tool-system.mdx | 2 + 4 files changed, 153 insertions(+) create mode 100644 sdk/arch/agent-profiles.mdx diff --git a/docs.json b/docs.json index a249468c0..1943163fd 100644 --- a/docs.json +++ b/docs.json @@ -339,6 +339,7 @@ "pages": [ "sdk/arch/overview", "sdk/arch/design", + "sdk/arch/agent-profiles", { "group": "SDK Components", "pages": [ diff --git a/sdk/arch/agent-profiles.mdx b/sdk/arch/agent-profiles.mdx new file mode 100644 index 000000000..5f2358e8c --- /dev/null +++ b/sdk/arch/agent-profiles.mdx @@ -0,0 +1,149 @@ +--- +title: Agent Profiles and Launch Composition +description: How stored profiles, server policy, tool availability, and client application additions compose a conversation agent. +--- + +An **Agent Profile** is a named, reusable specification for launching an agent. It stores durable user intent, such as the agent kind, referenced LLM profile, tool selection, and MCP server selection. It is not a running agent and does not contain resolved credentials. + +The agent server resolves a profile when a conversation starts. It combines the stored profile with server-owned policy and explicit additions from the client application, then persists the resulting agent with the conversation. + +## Design Goals + +Agent Profiles follow four principles: + +- **Portable profiles:** A profile can be launched by Agent Canvas, another client application, or directly through the agent-server API. +- **Application-neutral storage:** Profiles do not contain client-specific tools, deployment URLs, or resolved secrets unless the user explicitly selected them as profile configuration. +- **Server-owned resolution:** The agent server resolves references and produces the final agent used by the conversation. +- **Stable conversations:** A conversation resumes from its materialized agent rather than re-resolving the current version of its profile. + +## Architecture + +```mermaid +flowchart LR + Modules["Tool Modules"] -->|register implementations| Registry["Runtime Tool Registry"] + Baseline["Server Baseline"] --> Compose["Launch Composition"] + Profiles["Agent Profile Store"] -->|load by profile ID| Compose + Client["Client Application"] -->|profile ID and launch additions| Compose + Registry -->|validate and resolve tools| Compose + Compose --> Agent["Materialized Agent"] + Agent --> Conversation["Persisted Conversation"] +``` + +### Component Responsibilities + +| Component | Owns | Does Not Own | +| --- | --- | --- | +| **Tool module and registry** | Tool names, factories, and runtime availability | Whether a client or profile selects the tool | +| **Agent Profile** | Durable, secret-free agent configuration and references | Client-specific launch context or resolved credentials | +| **Client application** | Profile selection and application-specific launch additions | Profile resolution or server baseline policy | +| **Agent server** | Profile storage, validation, reference resolution, launch composition, and conversation persistence | Client-specific tool names or product behavior | +| **Conversation** | The materialized agent and profile provenance used for resume | Live synchronization with later profile edits | + +## Availability Is Not Selection + +Registering a tool makes its implementation available to the runtime. Registration alone does not decide whether the tool is included in an agent. + +For example, Agent Canvas can preload and register `canvas_ui`. Canvas then requests that tool as an application-specific launch addition. The agent server does not need Canvas-specific policy. Another client can use the same mechanism to add a tool such as `post_on_slack`. + +This separation keeps the tool registry reusable: + +1. A runtime or deployment makes tool implementations available. +2. A profile selects portable agent capabilities. +3. A client application adds capabilities required for that launch. +4. The agent server validates and composes the final agent. + +## Launch Flow + +```mermaid +sequenceDiagram + participant Client as Client Application + participant Server as Agent Server + participant Store as Profile Store + participant Registry as Tool Registry + participant Conversation + + Client->>Server: Start conversation with profile ID and launch additions + Server->>Store: Load profile + Store-->>Server: Stored profile and revision + Server->>Server: Resolve LLM, MCP, skills, and profile tools + Server->>Registry: Validate and instantiate selected tools + Registry-->>Server: Tool implementations + Server->>Server: Apply client launch additions + Server->>Conversation: Persist materialized agent and profile provenance + Server-->>Client: Conversation information +``` + +The launch request does not modify the stored profile. Editing a profile later also does not change conversations that were already launched from it. + +## Tool Composition + +Tool composition has four distinct layers: + +1. **Runtime-available tools:** Implementations registered in the current agent-server process. +2. **Server baseline:** The standard tools selected by the agent server when a profile inherits tools. +3. **Profile-selected tools:** The portable tool choice stored in the Agent Profile. +4. **Client launch additions:** Application-specific tools added for one conversation launch. + +The server baseline is independent of any profile whose name happens to be `default`. Renaming or editing that profile does not change server policy. + +For an OpenHands Agent Profile, the `tools` field controls only the profile-selected layer: + +| Profile `tools` | Profile-Resolved Tools | +| --- | --- | +| `null` | Inherit the server baseline | +| `[]` | Select no profile tools | +| Non-empty list | Use that profile list exactly | + +Client launch additions are applied after profile resolution. If Agent Canvas adds `canvas_ui`, the resulting composition is: + +| Profile `tools` | Profile-Resolved Tools | Canvas Addition | Materialized Tools | +| --- | --- | --- | --- | +| `null` | Server baseline | `canvas_ui` | Server baseline plus `canvas_ui` | +| `[]` | None | `canvas_ui` | `canvas_ui` | +| `[{"name": "terminal"}]` | `terminal` | `canvas_ui` | `terminal` plus `canvas_ui` | + + + An explicit profile list is exact within the profile layer. A client launch addition is a separate, visible modification. To launch a completely tool-free agent, the client must not add application-specific tools. + + +The server validates every selected or added tool against the runtime registry. An unavailable tool must fail the launch instead of silently producing a different agent. + +## Launch-Only Context + +Some context belongs to the client application or deployment rather than the reusable profile. Examples include instructions for reaching services available only in the current runtime. + +Clients send this information as an additive launch override. The server applies it after profile resolution. Launch overrides cannot replace the profile's LLM or other durable configuration. + +The launch override is folded into the materialized agent and excluded from the stored request metadata. This prevents the override from being applied twice when the conversation resumes. + +## Persistence and Provenance + +When a profile launches a conversation, the server stores: + +- The fully materialized agent, including resolved tools and launch additions. +- The stable profile ID and the profile revision used at launch. +- The conversation-scoped configuration and secret references needed for restore. + +The server does not re-resolve the profile during resume. This provides deterministic behavior when a profile is renamed, edited, or deleted after a conversation starts. + +The runtime must still provide implementations for tools referenced by the materialized agent. Client applications that introduce custom server-side tools should preload those modules before conversations are restored. + +## Compatibility and Migration + +Older clients can construct inline agents instead of launching by profile ID. The agent server exposes its resolved baseline tool list as `default_tools` through `/server_info` so those clients do not need to duplicate server policy. + +Clients should feature-detect the required profile-launch fields instead of inferring support from a version number alone. When the contract is unavailable, they can use their existing inline-agent fallback. + +Legacy profile migration is deliberately narrow. A schema-v1, untouched revision-0 OpenHands profile named `default` that was seeded with `tools: []` migrates to `tools: null`. User-created profiles and explicit empty lists remain unchanged. + +## ACP Profiles + +ACP agents delegate prompt construction and tool execution to an ACP subprocess. Their tools are not resolved through the OpenHands profile tool-composition path described above. Shared profile behavior, such as stable identity, references, revision provenance, and conversation snapshots, still applies. + +## See Also + +- [Agent Architecture](/sdk/arch/agent) +- [Tool System and MCP](/sdk/arch/tool-system) +- [Conversation Architecture](/sdk/arch/conversation) +- [Remote Agent Server](/sdk/guides/agent-server/overview) +- [Manage Agent Profiles in Agent Canvas](/openhands/usage/agent-canvas/agent-profiles) diff --git a/sdk/arch/overview.mdx b/sdk/arch/overview.mdx index 5ef666f22..a6152cdc5 100644 --- a/sdk/arch/overview.mdx +++ b/sdk/arch/overview.mdx @@ -145,6 +145,7 @@ flowchart LR **Key Components:** - **[Agent](/sdk/arch/agent):** Implements the reasoning-action loop +- **[Agent Profiles](/sdk/arch/agent-profiles):** Store portable agent configuration and compose it with launch-time application context - **[Conversation](/sdk/arch/conversation):** Manages conversation state and lifecycle - **[LLM](/sdk/arch/llm):** Provider-agnostic language model interface with retry and telemetry - **[Tool System](/sdk/arch/tool-system):** Typed base class definitions for action, observation, tool, and executor; includes MCP integration diff --git a/sdk/arch/tool-system.mdx b/sdk/arch/tool-system.mdx index 114a89318..6f3f02ca1 100644 --- a/sdk/arch/tool-system.mdx +++ b/sdk/arch/tool-system.mdx @@ -235,6 +235,8 @@ Tools include optional `ToolAnnotations` based on the [Model Context Protocol (M The registry enables **dynamic tool discovery** and instantiation from tool specifications: +Registration makes a tool implementation available; it does not select the tool for an agent. [Agent Profile launch composition](/sdk/arch/agent-profiles) combines registered implementations with profile choices and client application additions. + ```mermaid %%{init: {"theme": "default", "flowchart": {"nodeSpacing": 30}} }%% flowchart LR From c1086fd5ad2aa1b0768125e52857785f7483131e Mon Sep 17 00:00:00 2001 From: Debug Agent Date: Wed, 15 Jul 2026 12:08:14 +0200 Subject: [PATCH 2/2] docs(sdk): distinguish client tools from launch context --- sdk/arch/agent-profiles.mdx | 127 ++++++++++++++++-------------------- sdk/arch/tool-system.mdx | 2 +- 2 files changed, 59 insertions(+), 70 deletions(-) diff --git a/sdk/arch/agent-profiles.mdx b/sdk/arch/agent-profiles.mdx index 5f2358e8c..3c7bcc73b 100644 --- a/sdk/arch/agent-profiles.mdx +++ b/sdk/arch/agent-profiles.mdx @@ -1,11 +1,11 @@ --- title: Agent Profiles and Launch Composition -description: How stored profiles, server policy, tool availability, and client application additions compose a conversation agent. +description: How stored profiles, client-defined tools, and launch context compose a conversation agent. --- An **Agent Profile** is a named, reusable specification for launching an agent. It stores durable user intent, such as the agent kind, referenced LLM profile, tool selection, and MCP server selection. It is not a running agent and does not contain resolved credentials. -The agent server resolves a profile when a conversation starts. It combines the stored profile with server-owned policy and explicit additions from the client application, then persists the resulting agent with the conversation. +The agent server resolves a profile when a conversation starts. The client can also supply client-defined tools and deployment-specific context for that launch. The server materializes the result and persists it with the conversation. ## Design Goals @@ -13,44 +13,67 @@ Agent Profiles follow four principles: - **Portable profiles:** A profile can be launched by Agent Canvas, another client application, or directly through the agent-server API. - **Application-neutral storage:** Profiles do not contain client-specific tools, deployment URLs, or resolved secrets unless the user explicitly selected them as profile configuration. -- **Server-owned resolution:** The agent server resolves references and produces the final agent used by the conversation. +- **Server-owned resolution:** The agent server resolves profile references and produces the final agent used by the conversation. - **Stable conversations:** A conversation resumes from its materialized agent rather than re-resolving the current version of its profile. ## Architecture ```mermaid flowchart LR - Modules["Tool Modules"] -->|register implementations| Registry["Runtime Tool Registry"] - Baseline["Server Baseline"] --> Compose["Launch Composition"] - Profiles["Agent Profile Store"] -->|load by profile ID| Compose - Client["Client Application"] -->|profile ID and launch additions| Compose - Registry -->|validate and resolve tools| Compose + Modules["Server Tool Modules"] -->|register implementations| Registry["Runtime Tool Registry"] + Profiles["Agent Profile Store"] -->|load by profile ID| Compose["Launch Composition"] + Registry -->|resolve profile tools| Compose + Client["Client Application"] -->|profile ID| Compose + Client -->|client_tools JSON specs| Compose + Client -->|deployment context| Compose Compose --> Agent["Materialized Agent"] Agent --> Conversation["Persisted Conversation"] + Conversation -->|client-tool actions| Client ``` ### Component Responsibilities | Component | Owns | Does Not Own | | --- | --- | --- | -| **Tool module and registry** | Tool names, factories, and runtime availability | Whether a client or profile selects the tool | -| **Agent Profile** | Durable, secret-free agent configuration and references | Client-specific launch context or resolved credentials | -| **Client application** | Profile selection and application-specific launch additions | Profile resolution or server baseline policy | -| **Agent server** | Profile storage, validation, reference resolution, launch composition, and conversation persistence | Client-specific tool names or product behavior | -| **Conversation** | The materialized agent and profile provenance used for resume | Live synchronization with later profile edits | +| **Server tool module and registry** | Server-executed tool names, factories, and runtime availability | Whether a profile selects a tool | +| **Agent Profile** | Durable, secret-free agent configuration and references | Client-specific UI tools, deployment context, or resolved credentials | +| **Client application** | Profile selection, client-executed tool definitions, and deployment context | Profile resolution or server tool defaults | +| **Agent server** | Profile storage, validation, reference resolution, launch composition, and conversation persistence | Client-specific product behavior | +| **Conversation** | The materialized agent, client tool specifications, and profile provenance used for resume | Live synchronization with later profile edits | -## Availability Is Not Selection +## Tool Selection -Registering a tool makes its implementation available to the runtime. Registration alone does not decide whether the tool is included in an agent. +Registering a server tool makes its implementation available to the runtime. Registration alone does not select the tool for an agent. -For example, Agent Canvas can preload and register `canvas_ui`. Canvas then requests that tool as an application-specific launch addition. The agent server does not need Canvas-specific policy. Another client can use the same mechanism to add a tool such as `post_on_slack`. +For an OpenHands Agent Profile, the `tools` field controls the server-executed tools selected by that profile: -This separation keeps the tool registry reusable: +| Profile `tools` | Resolved Server Tools | +| --- | --- | +| `null` | Use the standard OpenHands tool set | +| `[]` | Use no server tools | +| Non-empty list | Use that list exactly | + +The standard tool set is independent of any profile whose name happens to be `default`. Renaming or editing that profile does not change the standard tool set. + +## Client-Defined Tools + +A client application can send JSON `client_tools` specifications when it starts a conversation. The server adds those tools after resolving the inline agent or Agent Profile. When the agent calls one, the server emits its action over the conversation event stream and the client performs the product-specific behavior. + +Client-defined tools do not require a Python implementation in the agent-server runtime. Their names, descriptions, parameter schemas, and annotations travel with the conversation and are restored with it. + +For example, Agent Canvas sends `canvas_ui_control` as a client-defined tool. Its frontend handles the resulting action by selecting a file, preview, or application tab. Another client could use the same API for a tool such as `post_on_slack` without making either tool part of the server's standard tool set. + +Client-defined tools are additive to the profile's `tools` field: -1. A runtime or deployment makes tool implementations available. -2. A profile selects portable agent capabilities. -3. A client application adds capabilities required for that launch. -4. The agent server validates and composes the final agent. +| Profile `tools` | Resolved Server Tools | Canvas Client Tool | Materialized Tools | +| --- | --- | --- | --- | +| `null` | Standard OpenHands set | `canvas_ui_control` | Standard set plus `canvas_ui_control` | +| `[]` | None | `canvas_ui_control` | `canvas_ui_control` | +| `[{"name": "terminal"}]` | `terminal` | `canvas_ui_control` | `terminal` plus `canvas_ui_control` | + + + An explicit profile list is exact for server-executed tools. To launch a completely tool-free agent, the client must also omit `client_tools`. + ## Launch Flow @@ -59,83 +82,49 @@ sequenceDiagram participant Client as Client Application participant Server as Agent Server participant Store as Profile Store - participant Registry as Tool Registry participant Conversation - Client->>Server: Start conversation with profile ID and launch additions + Client->>Server: Start with profile ID, client_tools, and launch context Server->>Store: Load profile Store-->>Server: Stored profile and revision Server->>Server: Resolve LLM, MCP, skills, and profile tools - Server->>Registry: Validate and instantiate selected tools - Registry-->>Server: Tool implementations - Server->>Server: Apply client launch additions - Server->>Conversation: Persist materialized agent and profile provenance + Server->>Server: Add client-defined tools + Server->>Server: Append deployment context + Server->>Conversation: Persist materialized agent and provenance Server-->>Client: Conversation information ``` The launch request does not modify the stored profile. Editing a profile later also does not change conversations that were already launched from it. -## Tool Composition - -Tool composition has four distinct layers: - -1. **Runtime-available tools:** Implementations registered in the current agent-server process. -2. **Server baseline:** The standard tools selected by the agent server when a profile inherits tools. -3. **Profile-selected tools:** The portable tool choice stored in the Agent Profile. -4. **Client launch additions:** Application-specific tools added for one conversation launch. - -The server baseline is independent of any profile whose name happens to be `default`. Renaming or editing that profile does not change server policy. - -For an OpenHands Agent Profile, the `tools` field controls only the profile-selected layer: - -| Profile `tools` | Profile-Resolved Tools | -| --- | --- | -| `null` | Inherit the server baseline | -| `[]` | Select no profile tools | -| Non-empty list | Use that profile list exactly | - -Client launch additions are applied after profile resolution. If Agent Canvas adds `canvas_ui`, the resulting composition is: - -| Profile `tools` | Profile-Resolved Tools | Canvas Addition | Materialized Tools | -| --- | --- | --- | --- | -| `null` | Server baseline | `canvas_ui` | Server baseline plus `canvas_ui` | -| `[]` | None | `canvas_ui` | `canvas_ui` | -| `[{"name": "terminal"}]` | `terminal` | `canvas_ui` | `terminal` plus `canvas_ui` | - - - An explicit profile list is exact within the profile layer. A client launch addition is a separate, visible modification. To launch a completely tool-free agent, the client must not add application-specific tools. - - -The server validates every selected or added tool against the runtime registry. An unavailable tool must fail the launch instead of silently producing a different agent. - ## Launch-Only Context -Some context belongs to the client application or deployment rather than the reusable profile. Examples include instructions for reaching services available only in the current runtime. +Some instructions belong to the current deployment rather than a reusable profile. For example, a deployment can tell the agent how to reach runtime services that are available only for that launch. -Clients send this information as an additive launch override. The server applies it after profile resolution. Launch overrides cannot replace the profile's LLM or other durable configuration. +Clients send these instructions through `agent_launch_additions.system_message_suffix_append`. The server appends the value after resolving the inline agent or Agent Profile. Launch additions cannot replace the profile's LLM, tools, or other durable configuration. -The launch override is folded into the materialized agent and excluded from the stored request metadata. This prevents the override from being applied twice when the conversation resumes. +The server folds the suffix into the materialized agent and excludes `agent_launch_additions` from stored request metadata. This prevents the suffix from being applied twice when the conversation resumes. ## Persistence and Provenance When a profile launches a conversation, the server stores: -- The fully materialized agent, including resolved tools and launch additions. -- The stable profile ID and the profile revision used at launch. +- The fully materialized agent, including resolved server tools, client tools, and launch context. +- The client tool specifications needed to restore client-executed actions. +- The stable profile ID and profile revision used at launch. - The conversation-scoped configuration and secret references needed for restore. The server does not re-resolve the profile during resume. This provides deterministic behavior when a profile is renamed, edited, or deleted after a conversation starts. -The runtime must still provide implementations for tools referenced by the materialized agent. Client applications that introduce custom server-side tools should preload those modules before conversations are restored. +Server-executed tools referenced by the materialized agent must still be available when the conversation resumes. Client-defined tools remain executable by the connected client and do not require a server-side Python module. ## Compatibility and Migration -Older clients can construct inline agents instead of launching by profile ID. The agent server exposes its resolved baseline tool list as `default_tools` through `/server_info` so those clients do not need to duplicate server policy. - -Clients should feature-detect the required profile-launch fields instead of inferring support from a version number alone. When the contract is unavailable, they can use their existing inline-agent fallback. +Clients must only send `agent_launch_additions` to server releases that support it. When it is unavailable, a client can continue constructing its existing inline agent. The established `client_tools` API remains independent of that compatibility path. Legacy profile migration is deliberately narrow. A schema-v1, untouched revision-0 OpenHands profile named `default` that was seeded with `tools: []` migrates to `tools: null`. User-created profiles and explicit empty lists remain unchanged. +Older persisted conversations can still reference server-executed tool modules that current clients no longer use. Deployments can keep those modules importable for restore while all new conversations use client-defined tools. + ## ACP Profiles ACP agents delegate prompt construction and tool execution to an ACP subprocess. Their tools are not resolved through the OpenHands profile tool-composition path described above. Shared profile behavior, such as stable identity, references, revision provenance, and conversation snapshots, still applies. diff --git a/sdk/arch/tool-system.mdx b/sdk/arch/tool-system.mdx index 6f3f02ca1..372dbf1a4 100644 --- a/sdk/arch/tool-system.mdx +++ b/sdk/arch/tool-system.mdx @@ -235,7 +235,7 @@ Tools include optional `ToolAnnotations` based on the [Model Context Protocol (M The registry enables **dynamic tool discovery** and instantiation from tool specifications: -Registration makes a tool implementation available; it does not select the tool for an agent. [Agent Profile launch composition](/sdk/arch/agent-profiles) combines registered implementations with profile choices and client application additions. +Registration makes a server tool implementation available; it does not select the tool for an agent. [Agent Profile launch composition](/sdk/arch/agent-profiles) explains how profile-selected server tools compose with client-defined tools. ```mermaid %%{init: {"theme": "default", "flowchart": {"nodeSpacing": 30}} }%%