Skip to content

feat(agent-designer): reflect governed agent bindings in the chat-input (lock pickers)#603

Merged
philmerrell merged 1 commit into
developfrom
feature/agent-chat-input-lock
Jul 9, 2026
Merged

feat(agent-designer): reflect governed agent bindings in the chat-input (lock pickers)#603
philmerrell merged 1 commit into
developfrom
feature/agent-chat-input-lock

Conversation

@philmerrell

Copy link
Copy Markdown
Contributor

Summary

Closes the frontend half of the Agent binding-resolution work. The backend now governs an Agent's model/tool/skill bindings at invocation (#601, #602) — the agent's set wins regardless of what the client sends. But the chat-input still showed the model/tool/skill pickers as free-select, which was dishonest: the user could "change" a model the backend would ignore. This locks each picker to the active Agent's bindings, per primitive.

This is UI honesty, not enforcement — the backend remains the authority. Per-primitive: an agent that binds a model but no tools locks only the model; the rest stay free-select. Plain chat and legacy assistants are unchanged.

What changed

  • Session page (session.page.ts): inject AgentService/ToolService/SkillService; fetch the governed Agent alongside the assistant (agentId == assistantId) in loadAssistant; apply per-primitive locks from modelConfig/bindings, and release them when navigating to plain chat. Best-effort: the /agents surface may be disabled (404) or the assistant may be a legacy assistant with no bindings — every failure leaves the pickers free-select and never blocks the conversation.
  • ModelService / ToolService / SkillService: small agent-lock API (lockToAgent* / clearAgentLock + agentLocked/agentModelLocked). While locked, enabledToolIds/enabledSkillIds return the bound set (replace semantics, matching the backend), toggles no-op, and isToolShownEnabled/isSkillShownEnabled render the bound set honestly (greyed).
  • UI: model-dropdown shows a locked read-only chip; model-settings shows a "Set by agent" model row and a "This agent uses a fixed set of tools/skills" banner, with tool/skill/sub-tool toggles disabled while locked.

Tests

  • +5 tool-lock, +5 skill-lock, +4 model-lock service specs (ng test, 51 pass in the affected specs)
  • tsc clean; production build (AOT template validation) clean
  • No local preview (needs backend + AGENTS_API_ENABLED + auth) — see the manual test script in the PR discussion.

Known limitations (follow-up)

  • Model race: if the pinned model isn't in the user's loaded set yet, the dropdown disables but may show the fallback name until models load. (Models load on app init, so rare.)
  • Skill-lock banner only renders in skills chat-mode (the skills section is mode-gated); the backend still forces skill-mode + the bound skills regardless.

🤖 Generated with Claude Code

…ut (lock pickers)

The backend governs an Agent's model/tool/skill bindings at invocation (#601, #602) —
the agent's set wins regardless of what the client sends. The chat-input still showed
the model/tool/skill pickers as free-select, which was dishonest (a change the backend
ignores). This locks each picker to the active Agent's bindings, per primitive.

- Session page (`session.page.ts`): inject AgentService/ToolService/SkillService; fetch
  the governed Agent alongside the assistant (agentId == assistantId) in `loadAssistant`;
  apply per-primitive locks from `modelConfig`/`bindings`, and release them when navigating
  to plain chat. Best-effort: the /agents surface may be disabled (404) or the assistant
  may be a legacy assistant with no bindings — every failure leaves the pickers free-select.
- ModelService/ToolService/SkillService: add a small agent-lock API (`lockToAgent*` /
  `clearAgentLock` + `agentLocked`/`agentModelLocked`). While locked, `enabledToolIds`/
  `enabledSkillIds` return the bound set (replace semantics, matching the backend), toggles
  no-op, and `isToolShownEnabled`/`isSkillShownEnabled` render the bound set honestly.
- UI: model-dropdown shows a locked read-only chip ("set by this agent"); model-settings
  shows a "Set by agent" model row and a "This agent uses a fixed set of tools/skills"
  banner, with tool/skill/sub-tool toggles disabled + greyed while locked.

This is UI honesty, not enforcement — the backend remains the authority. Per-primitive:
an agent that binds a model but no tools locks only the model; the rest stay free-select.

Tests: +5 tool-lock, +5 skill-lock, +4 model-lock service specs (ng test, 51 pass);
`tsc` clean; production build (AOT template check) clean.

Known limitations (documented for follow-up): a model race if the pinned model isn't in
the user's loaded set yet (dropdown disables but may show the fallback name until models
load); the skill-lock banner only shows in skills chat-mode.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@philmerrell philmerrell merged commit 02680a8 into develop Jul 9, 2026
4 checks passed
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.

1 participant