Skip to content

spec: tab configs specify agent profile (#10171)#10229

Open
lonexreb wants to merge 6 commits intowarpdotdev:masterfrom
lonexreb:spec/10171-tab-config-agent-profile
Open

spec: tab configs specify agent profile (#10171)#10229
lonexreb wants to merge 6 commits intowarpdotdev:masterfrom
lonexreb:spec/10171-tab-config-agent-profile

Conversation

@lonexreb
Copy link
Copy Markdown
Contributor

@lonexreb lonexreb commented May 6, 2026

Spec for #10171. New profile field on agent-typed panes in tab configs. When the tab opens, the named profile is applied before any agent input is dispatched. Missing profile = default + one-time toast.

Closes (spec-only) #10171.

@cla-bot cla-bot Bot added the cla-signed label May 6, 2026
@github-actions github-actions Bot added the external-contributor Indicates that a PR has been opened by someone outside the Warp team. label May 6, 2026
@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 6, 2026

@lonexreb

I'm starting a first review of this spec-only pull request.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

@dhruvac29
Copy link
Copy Markdown

Thanks for writing this up. A few details seem worth aligning with the issue thread before this spec lands:

  1. The issue thread now has maintainer guidance that tab configs should reference profiles by display name, and if multiple profiles share the same display name Warp should error instead of choosing one. Could we add that to the behavior contract, acceptance criteria, and test plan?

  2. B3 says omitting profile preserves today’s behavior, but the parenthetical says “default profile.” The original issue says today’s behavior is whichever profile was last used. It would be good to clarify whether omitted profile truly preserves the current last-used behavior or intentionally switches to default.

  3. Since this is spec-only, I’d avoid a closing keyword for Feature request: Allow tab configs to specify an agent profile for agent-mode panes #10171 unless maintainers want the implementation issue closed by the spec PR. Refs #10171 may be safer than Closes ... #10171.

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

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

Overview

This spec adds a profile field for agent-typed tab-config panes and covers core parsing, defaulting, UI picker, round-trip, and missing-profile behavior.

Concerns

  • The spec needs to define the trust/consent model before a tab config can switch an Agent Mode pane to a named profile and dispatch input under that profile.
  • The missing-profile "one-time toast" behavior is underspecified.
  • The test plan should explicitly cover the ordering guarantee that profile application completes before any initial agent input is dispatched.

Security

  • A shared or imported tab config can select a high-autonomy profile by display name before agent input runs; the spec should state the user-visible disclosure or confirmation behavior for this privilege-affecting binding.

Verdict

Found: 0 critical, 2 important, 1 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread specs/GH10171/SPEC.md Outdated
type = "agent"
profile = "Coder devbox"
```
- B2. When the tab config opens, the named profile is applied to
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] [SECURITY] Applying a profile from a tab config before dispatching agent input lets a shared or imported config select a higher-autonomy profile and immediately run under it. Specify the trust/consent behavior, such as user-visible disclosure or confirmation before input runs.

Comment thread specs/GH10171/SPEC.md Outdated
- B2. When the tab config opens, the named profile is applied to
the pane before any agent input is dispatched. The profile
lookup is by display name; if no matching profile exists, the
pane opens with the default profile and a one-time toast warns
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] Define the scope of "one-time toast": per pane open, per tab config, per missing profile name, or per app session, including behavior when multiple panes reference missing profiles.

Comment thread specs/GH10171/SPEC.md Outdated
## Test plan

- T1. Schema round-trip with the new field.
- T2. Open path applies the named profile when present.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 [SUGGESTION] Add a test where the agent pane has initial input and assert the selected profile is applied before that input is dispatched.

Co-Authored-By: Warp <agent@warp.dev>
@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 7, 2026

/oz-review

@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 7, 2026

@lonexreb

I'm re-reviewing this spec-only pull request in response to a review request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

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

Overview

Reviewed the spec-only change adding a profile field for agent tab-config panes. The proposed behavior covers the happy path, omitted profile behavior, round-tripping, UI picker, and confirmation before dispatch for a resolved profile.

Concerns

  • Profile lookup by display name is underspecified when names are duplicated, which can select the wrong autonomy/environment profile.
  • The confirmation requirement does not explicitly cover the existing tab-config commands input path or other open-time agent inputs.
  • Missing-profile fallback does not define what happens when the pane also has initial input, so an implementation could dispatch under the default profile without confirmation.

Security

  • The unresolved duplicate-name and missing-profile cases can cause initial agent input to run under a different profile than the tab config author or user expected.

Verdict

Found: 0 critical, 3 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread specs/GH10171/SPEC.md Outdated
type = "agent"
profile = "Coder devbox"
```
- B2. When the tab config opens, profile lookup is by trimmed,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] [SECURITY] Lookup by display name needs a duplicate-name rule or a uniqueness requirement; otherwise two profiles named Coder devbox can resolve to the wrong autonomy/environment settings.

Comment thread specs/GH10171/SPEC.md Outdated
case-sensitive display name. If the profile exists and the agent
pane has no initial input to auto-dispatch, the named profile is
applied before the pane is shown.
- B2a. If the profile exists and the agent pane has initial input
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] Define which tab-config fields count as initial agent input, especially the existing commands array, so every auto-dispatch path is gated by the confirmation requirement.

Comment thread specs/GH10171/SPEC.md Outdated
default profile and dispatches the initial input. Cancelling opens
the pane with the initial input preserved as an editable draft and
dispatches nothing.
- B2b. If no matching profile exists, the pane opens with the
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] [SECURITY] Missing-profile fallback must specify the initial-input case; if the named profile is absent, no input should dispatch under the default profile unless the user explicitly confirms that profile.

@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 8, 2026

Round-1 fixes for oz-for-oss review: (1) added Trust & Consent Model — imported/shared configs require inline confirmation before agent dispatch; user-saved configs are pre-trusted; (2) defined missing-profile behavior with Disabled-Agent state holding initial input AND commands; (3) resolved duplicate-name lookup via (name, source) pairs and qualified source:name syntax; (4) extended confirmation gate to cover all open-time agent inputs (initial prompt, commands array, etc.); (5) added explicit ordering test for profile-bind-before-dispatch; (6) updated acceptance criteria to cover ambiguous-name, missing-profile, imported vs owned config paths.

@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 8, 2026

/oz-review

@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 8, 2026

@lonexreb

I'm re-reviewing this spec-only pull request in response to a review request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

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

Overview

This spec adds a profile field for agent panes in tab configs and defines profile resolution, imported-config consent, disabled-agent fallback, and tests.

Concerns

  • The profile identity model contradicts the ambiguous-name behavior, so implementation cannot know whether same-source duplicate names are legal or resolvable.
  • Imported-config trust and disclosure need tighter security requirements so external TOML cannot self-declare as owned and the consent card exposes exact open-time inputs.
  • The Cancel flow can leave imported draft input in an elevated default profile, which weakens the intended consent gate.
  • The qualified source:name syntax needs parsing rules for profile names that contain :.

Security

  • Treat trust markers as local metadata only: imported files must default to imported and must not be able to carry an authoritative owned value.
  • Require the confirmation UI to show exact, inspectable prompts and command entries rather than an unspecified summary.
  • Define a safe Cancel state when the default profile is elevated.

Verdict

Found: 1 critical, 3 important, 1 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread specs/GH10171/SPEC.md
(e.g. `"Coder devbox"`) OR a qualified
`source:name` form (e.g. `"team:reviewer"`,
`"user:Coder devbox"`, `"builtin:Default"`).
- B1b. Profiles are uniquely identified internally by the
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚨 [CRITICAL] B1b says (name, source) uniquely identifies a profile, but B-LOOKUP and A-AMBIG require multiple profiles with the same name inside one source. Either enforce per-source name uniqueness and remove intra-source ambiguity, or add a stable profile ID for exact lookup.

Comment thread specs/GH10171/SPEC.md Outdated

### Trust & Consent model

- B-TRUST. Each tab config carries an internal trust marker
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] [SECURITY] Specify that the trust marker is local metadata only: imported TOML/share links cannot set owned, and any missing or externally supplied marker must be treated as imported, otherwise a shared config can bypass the consent gate.

Comment thread specs/GH10171/SPEC.md Outdated
then the pane MUST display an inline disclosure card before
dispatching ANY agent input. The card states:
> "This tab config wants to use the **'[name]'** profile
> (autonomy: **[level]**) and will run **[summary of input]**
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] [SECURITY] The disclosure cannot rely on an unspecified summary of input; require the card to show the exact initial prompt and command entries, or an expandable exact view, so imported configs cannot hide dangerous open-time dispatch behind a benign summary.

Comment thread specs/GH10171/SPEC.md Outdated
inputs uniformly — the initial prompt field, the `commands`
array, and any future tab-config-driven dispatch path. None
may dispatch until the user has confirmed (when required).
- B-TRUST-5. Cancel on the disclosure card opens the pane with
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] [SECURITY] Cancel falls back to the default profile even when the default profile is elevated; specify a safe state such as Disabled-Agent/manual-only/no draft dispatch so an imported draft cannot later run under elevated default autonomy after the user declined confirmation.

Comment thread specs/GH10171/SPEC.md
```
- B1a. The `profile` field accepts EITHER a bare display name
(e.g. `"Coder devbox"`) OR a qualified
`source:name` form (e.g. `"team:reviewer"`,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 [SUGGESTION] Define escaping or validation for profile names containing :; without that, the source:name form is ambiguous and may not round-trip for existing display names.

@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 8, 2026

Round-2 fixes: (1) CRITICAL resolved — single-source name uniqueness is now an enforced invariant (B-IDENTITY); the profile store rejects create/import/rename collisions. Only cross-source ambiguity remains and is resolved deterministically by precedence (user > team > builtin); (2) trust marker is LOCAL-ONLY in ~/.config/warp/tab_config_trust.json, keyed by (canonical_path_hash, content_hash); imported files always default to imported; in-file trust markers are stripped on import (B-TRUST-STRIP); (3) consent card shows exact verbatim inputs (full prompt text + commands array + all open-time agent inputs); (4) Cancel rolls back import (no input retention, no draft); 'Open with default profile' clears all agent inputs to prevent piggyback elevation; (5) source:name parser splits on first unescaped :; backslash-escape rules defined; tests T_qualified_name_with_colon and T_qualified_name_with_backslash added.

@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 8, 2026

/oz-review

@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 8, 2026

@lonexreb

I'm re-reviewing this spec-only pull request in response to a review request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

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

Overview

This spec adds profile selection for agent panes in tab configs and defines profile resolution, trust, consent, fallback, and test-plan behavior.

Concerns

  • The trust upgrade path from settings can bypass the consent card's verbatim disclosure.
  • Multi-pane consent/cancel behavior is underspecified.
  • Consent rendering does not specify inert/escaped display for untrusted prompts and commands.
  • Session-scoped consent semantics conflict with the imported-until-trusted model.

Security

  • Imported tab configs can contain deceptive prompts/commands; the spec needs an explicit inert rendering contract.
  • Trust promotion outside the consent card needs the same disclosure before sidecar writes.

Verdict

Found: 0 critical, 4 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread specs/GH10171/SPEC.md Outdated
defaults to `imported` until the user re-trusts.
- B-TRUST-UPGRADE. Upgrading an `imported` config to `trusted`
requires an explicit user action: a "Trust this tab config"
control on the consent card (B-CONSENT) or in the Tab Configs
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] [SECURITY] Allowing "Trust this tab config" from settings can bypass the consent card's verbatim review; require the settings flow to show the same profile/autonomy/input disclosure and confirmation before writing the trusted sidecar entry.

Comment thread specs/GH10171/SPEC.md
has been raised), OR
- any open-time agent input (initial prompt field, `commands`
array, or any other tab-config-driven dispatch path),
then the pane MUST display an inline consent card before
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] The per-pane consent wording conflicts with B-CANCEL's tab-level rollback for multi-pane configs; define whether consent is gathered once for the whole tab before any panes open, and how mixed gated panes/actions are handled.

Comment thread specs/GH10171/SPEC.md
characters, show the first 800 characters followed by an
`[expand]` toggle that reveals the rest. The card MUST NOT
truncate silently.
- **`commands` array**: every entry rendered on its own line
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] [SECURITY] The consent card renders untrusted prompts/commands verbatim but does not require inert rendering or visible escaping for control characters/newlines; specify escaped, non-interpreted display so malicious inputs cannot disguise what will dispatch.

Comment thread specs/GH10171/SPEC.md Outdated
B-TRUST-UPGRADE.
2. `[Open with default profile]` — see B-CANCEL-DEFAULT.
3. `[Cancel]` — see B-CANCEL.
- B-CONSENT-SESSION. For an `imported` (not yet trusted) config,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ [IMPORTANT] [SECURITY] This implies same-session reopens may skip consent without a trusted sidecar entry; define the session-consent key and content invalidation rules, or require the card on every open until the config is trusted.

@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 8, 2026

Round-3 review fixes (commit 9c587af):

  • Trust-upgrade-from-settings disclosure (B-TRUST-UPGRADE-DISCLOSURE): clicking 'Trust this tab config' from the settings row now requires a Trust-review modal with the SAME verbatim B-CONSENT-CONTENT (profile, autonomy, prompt, commands, other inputs) rendered inert per B-CONSENT-INERT. Sidecar writes from settings are forbidden without that gate. Closes the bypass where settings could promote a malicious imported config without ever showing its open-time inputs.
  • Multi-pane consent / cancel (B-CONSENT-MULTIPANE, B-CANCEL-MULTIPANE, B-CANCEL-DEFAULT-MULTIPANE, B-CONSENT-MULTIPANE-PROMOTE): per-pane consent cards in source order with 'Pane K of N' header; ALL agent processes are gated until every consent-gated pane resolves; [Cancel] on any card rolls back the entire tab open (no partial opens); [Open with default profile] is per-pane; the 'Trust this tab config' checkbox is shared across panes and the sidecar write is deferred until all panes resolve with [Open with profile].
  • Inert rendering contract (B-CONSENT-INERT): every verbatim field on the consent card and the Trust-review modal is rendered inert: no execution, no live links, ANSI escapes (incl. OSC 8 hyperlinks) surfaced as visible escaped glyphs, bidi/RTL-override controls (U+202A–U+202E, U+2066–U+2069) replaced with visible placeholders, zero-width / confusable characters (ZWJ, ZWNJ, ZWSP) flagged, control characters escaped, read-only typography. Tests T-CONSENT-INERT-ANSI / -BIDI / -ZWSP cover the spoof vectors.
  • Imported-until-trusted reconciled (B-CONSENT-EVERY-OPEN): the prior 'session-scoped consent' wording is replaced. Imported configs require consent on EVERY open (same session, new session, multi-pane open) — there is NO per-session memory of prior consent. Only sidecar trust per B-TRUST-UPGRADE persists; this resolves the conflict with the imported-until-trusted model.

@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 8, 2026

/oz-review

@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 8, 2026

Round-4 review addressed: tightened B-TRUST-UPGRADE to enumerate the only two trust-write surfaces (consent-card checkbox + settings modal) and explicitly forbid all other sidecar write paths. The settings surface now mandates B-TRUST-UPGRADE-DISCLOSURE as a precondition. Multi-pane consent/cancel (B-CONSENT-MULTIPANE, B-CANCEL-MULTIPANE), inert/escaped rendering (B-CONSENT-INERT), and session-scope reconciliation (B-CONSENT-EVERY-OPEN) remain in place from prior rounds.

@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 8, 2026

/oz-review

rgatx added a commit to rgatx/warp that referenced this pull request May 8, 2026
Adds support for specifying an AI execution profile by display name on
agent-typed panes in tab configurations.

Schema:
- `TabConfigPaneNode` gains `profile: Option<String>` (deny_unknown_fields
  is preserved; the field is trimmed and empty-after-trim is treated as
  omitted).
- `PaneTemplateType::PaneTemplate` gains `agent_profile_name: Option<String>`
  to carry the resolved name from the tab-config layer to the pane-launch
  layer.

Lookup helper:
- New `AIExecutionProfilesModel::find_profile_by_display_name` resolves a
  trimmed name against `AIExecutionProfile::display_name`. Returns
  `ProfileLookupError::NotFound` for no match and
  `ProfileLookupError::Ambiguous { count }` when multiple profiles share
  the requested display name. This honors moirahuang's binding direction
  in warpdotdev#10171: error on duplicate names rather than silently picking one.

Apply paths:
- Immediate launch (`pane_group::PaneGroup::pane_tree_from_template_recursive`)
  applies the profile via `set_active_profile` before
  `enter_agent_view_for_new_conversation`. A per-launch
  `HashSet<String>` deduplicates the missing-profile toast so a tab config
  with multiple panes referencing the same missing name produces a single
  toast.
- Deferred launch (`TerminalView` after `PendingCommandCompleted`) stashes
  the profile name on a new `pending_agent_profile_name` field and
  applies it via the mirror helper just before the deferred
  `enter_agent_view_for_new_conversation` call.

UX policy (per FINAL_PLAN locked decisions):
- Missing name: fall back to default profile + warning toast (recoverable
  for typos / unsynced profiles).
- Ambiguous name: abort agent-mode entry with an error toast pointing the
  user at Settings → Agents → Profiles. The pane stays as a terminal.
- `profile` set on a non-agent pane: `log::warn!` and ignore (matches the
  existing soft-warn precedent in `tab_config.rs`).
- Omitted: preserve current behavior (no `set_active_profile` call;
  `active_profile(Some(id))` already falls back to default).

Tests:
- 7 unit tests in `profiles_tests.rs` covering unique match, NotFound,
  Ambiguous, default-resolves, two-Untitled-collide, trim, and
  empty-input cases.
- 5 unit tests in `tab_config_tests.rs` covering schema propagation,
  whitespace trim, empty-as-omitted, terminal-pane-with-profile passes,
  and TOML round-trip.

Trust/consent:
- Profile selection is permission-affecting via
  `BlocklistAIPermissions::active_permissions_profile`. Disclosure is via
  the agent input footer chrome (already shows the active profile);
  tab-config TOML edits serve as primary user consent.

Wiring:
- `TerminalView::Event::ShowToast` (already a variant) is now propagated
  to `pane_group::Event::ShowToast` in `handle_terminal_view_event` so
  the deferred-path toast actually reaches the workspace toast stack.

Closes warpdotdev#10171
Refs warpdotdev#10229
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed external-contributor Indicates that a PR has been opened by someone outside the Warp team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants