这是indexloc提供的服务,不要输入任何密码
Skip to content

Conversation

@K-Mistele
Copy link
Contributor

@K-Mistele K-Mistele commented Oct 14, 2025

What problem(s) was I solving?

Users couldn't easily reference Claude Code sub-agents in the WUI prompt input. While Claude supports sub-agents through the Task tool, there was no UI affordance to discover and mention them using the familiar @ pattern that works for files. Users had to remember exact agent names and type them manually.

What user-facing changes did I ship?

  • @agent mentions in prompt input: Type @ to see available sub-agents alongside files in the mention dropdown
  • Agent discovery: Automatically discovers agents from .claude/agents/ (local) and ~/.claude/agents/ (global) directories
  • Fuzzy search: Type partial agent names (e.g., @code) to filter agents using fuzzy matching
  • Visual distinction: Agents appear with a HatGlasses icon (matching the icon used for subagent events) to distinguish them from files/folders
  • Seamless integration: Selected agents insert as @agent-<name> mentions that Claude recognizes and can invoke

How I implemented it

Backend (Go daemon)

  • Added /api/v1/agents/discover endpoint that scans .claude/agents/ directories for markdown files with YAML frontmatter
  • Parses agent metadata (name, description, tools, model) from YAML frontmatter between --- markers
  • Validates agent names (lowercase letters and hyphens only)
  • Handles deduplication where local agents override global ones with the same name
  • Returns agents in @agent-<name> format ready for mentions

Frontend (React/TypeScript)

  • Extended FuzzyFileMentionList component to fetch agents alongside files when @ is typed
  • Added fuzzy matching for agent names using the fuzzy npm package
  • Updated FileMentionNode to detect agent mentions and render with appropriate HatGlasses icon
  • Fixed several UI bugs discovered during implementation:
    • Replaced incorrect HardHatIcon with HatGlasses icon
    • Fixed double @ symbol issue by stripping @ from both id and label fields
    • Added agent detection logic to show correct icon in mention badges

API Changes

  • Updated OpenAPI spec with new /agents/discover endpoint and Agent schema
  • Generated TypeScript SDK types for agent discovery
  • Renamed SlashCommand source constants for consistency (api.Local → api.SlashCommandSourceLocal)

How to verify it

Manual Testing

  1. Start the daemon: Ensure hld daemon is running on port 2136
  2. Open WUI: Navigate to http://localhost:1420 and open/create a Claude Code session
  3. Test agent discovery:
    • Type @ in the prompt input
    • Verify agents appear at the top of the dropdown with HatGlasses icon
    • Verify files still appear below agents with appropriate icons
  4. Test fuzzy search:
    • Type @code and verify it matches @agent-codebase-locator
    • Type @web and verify it matches @agent-web-search-researcher
  5. Test selection:
    • Click an agent or press Enter to select
    • Verify the mention badge shows @agent-<name> (single @, not double)
    • Verify the badge has the HatGlasses icon
  6. Test keyboard navigation:
    • Use arrow keys to navigate the dropdown
    • Press Escape to close
    • Press Tab/Enter to select
  7. Test with custom agents:
    • Create a test agent in .claude/agents/test.md with valid YAML frontmatter
    • Restart daemon and verify your custom agent appears

Automated Verification

  • WUI checks pass: make -C humanlayer-wui check
  • HLD checks pass: make -C hld check (fails due to unrelated test constant renaming)
  • TypeScript compilation: No type errors
  • Daemon endpoint works: curl -X POST http://localhost:2136/api/v1/agents/discover -H "Content-Type: application/json" -d '{"workingDir": "."}'

Description for the changelog

feat: Add @agent-mention support in WUI prompt input with fuzzy search and visual distinction using HatGlasses icon

https://www.loom.com/share/8ab2053b1e8b4c59861c567fadf652da


Important

Adds @agent mention support in WUI with fuzzy search and visual distinction using HatGlasses icon, including backend agent discovery and frontend integration.

  • Behavior:
    • Introduces @agent mentions in WUI, allowing users to type @ to see available sub-agents and files.
    • Agents are discovered from .claude/agents/ (local) and ~/.claude/agents/ (global) directories.
    • Supports fuzzy search for agent names using the fuzzy npm package.
    • Agents are visually distinguished with a HatGlasses icon.
  • Backend:
    • Adds /api/v1/agents/discover endpoint in agents.go to discover agents from directories.
    • Parses agent metadata from YAML frontmatter and handles deduplication.
  • Frontend:
    • Extends FuzzyFileMentionList in FuzzyFileMentionList.tsx to include agents in search results.
    • Updates FileMentionNode in FileMentionNode.tsx to render agent mentions with HatGlasses icon.
  • API Changes:
    • Updates OpenAPI spec with new /agents/discover endpoint and Agent schema.
    • Generates TypeScript SDK types for agent discovery.
  • Misc:
    • Adds fuzzy package to package.json for fuzzy search functionality.

This description was created by Ellipsis for e3f52dd. You can customize this summary. It will automatically update as commits are pushed.

Adds support for @agent mentions in the Claude Code WUI prompt input, enabling
users to reference sub-agents defined in .claude/agents/ directories.

Backend changes:
- Add /api/v1/agents/discover endpoint to scan and parse agent YAML files
- Wire up AgentHandlers in server implementation
- Add YAML parsing dependency for agent frontmatter

Frontend changes:
- Extend FuzzyFileMentionList to fetch and display agents alongside files
- Show agents with HatGlasses icon in dropdown (fixed from HardHatIcon)
- Update FileMentionNode to detect and render agent mentions with correct icon
- Fix double @ symbol issue by stripping @ from both id and label fields
- Add fuzzy matching for agent names using fuzzy npm package

Fixes:
- Replace HardHatIcon with correct HatGlasses icon for agents
- Remove double @ symbol in mention badges (strip from both id and label)
- Show correct icon in mention badges based on type (agent/file/directory)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed everything up to 41509ce in 1 minute and 39 seconds. Click for details.
  • Reviewed 1863 lines of code in 21 files
  • Skipped 0 files when reviewing.
  • Skipped posting 3 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. humanlayer-wui/src/components/internal/SessionDetail/components/FuzzyFileMentionList.tsx:134
  • Draft comment:
    Verify that the fuzzy library returns the matched character positions in the property used. Using 'result.index || []' assumes the property is named 'index'; some implementations may return 'indexes' instead. Ensure this aligns with the library’s output.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the PR author to verify the behavior of a library, which violates the rule against asking for confirmation or verification. It does not provide a specific suggestion or point out a clear issue with the code. Therefore, it should be removed.
2. humanlayer-wui/src/components/internal/SessionDetail/components/FuzzyFileMentionList.tsx:189
  • Draft comment:
    The ArrowUp key handler uses a modulo expression with '|| 0'. Since modulo always yields a valid index when results.length > 0, the '|| 0' may be redundant and could be simplified for clarity.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
3. humanlayer-wui/src/components/internal/SessionDetail/components/FuzzyFileMentionList.tsx:102
  • Draft comment:
    Consider using Promise.allSettled instead of Promise.all when fetching files and agents. This would enable handling partial results if one API call fails, rather than causing the entire search to fail.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 30% vs. threshold = 50% The suggestion has merit - Promise.allSettled would allow showing partial results if one API fails. However, the current error handling is intentionally conservative - if either request fails, it shows an error and clears results. This is a reasonable UX choice since partial results could be confusing. The current approach is simpler and clearer. The comment identifies a real technical possibility for improvement. Partial results could be better than no results in some cases. While technically possible, the current all-or-nothing approach is a valid design choice that keeps the UX simpler and more predictable. The comment suggests a change without clear evidence it would improve the user experience. The comment should be removed. While technically valid, it suggests a change to intentional error handling behavior without strong evidence it would improve the user experience.

Workflow ID: wflow_yN8jLdAMbDwlrA36

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

…andlers

- Update test files to use new constant names (api.SlashCommandSourceLocal/Global)
- Add AgentHandlers parameter to NewServerImpl calls in test files
- Replace deprecated ioutil.ReadFile with os.ReadFile

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed 983aaf5 in 1 minute and 5 seconds. Click for details.
  • Reviewed 144 lines of code in 4 files
  • Skipped 0 files when reviewing.
  • Skipped posting 5 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. hld/api/handlers/agents.go:41
  • Draft comment:
    The regex '^[a-z-]+$' is very strict. Confirm that this pattern meets all agent naming requirements. If agents might need to include digits or underscores in the future, consider updating the regex.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
2. hld/api/handlers/agents.go:85
  • Draft comment:
    Replacing ioutil.ReadFile with os.ReadFile is appropriate and follows modern Go best practices since ioutil is deprecated.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
3. hld/api/handlers/files_test.go:274
  • Draft comment:
    The call to NewServerImpl has been updated to include a nil for AgentHandlers. This ensures the test suite remains compatible with the new server signature. Verify that passing nil here is acceptable for tests not involving agent functionality.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
4. hld/api/handlers/sessions_slash_commands_test.go:327
  • Draft comment:
    The tests now consistently use the updated constants (api.SlashCommandSourceLocal and api.SlashCommandSourceGlobal) instead of the old api.Local/api.Global. This improves clarity in command source assignments—ensure that all scenarios reflect this change correctly.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
5. hld/api/handlers/testutil_test.go:27
  • Draft comment:
    Passing nil for AgentHandlers in the NewServerImpl call aligns with the updated constructor signature and ensures tests that don't involve agent functionality remain unaffected.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None

Workflow ID: wflow_pgM8PB6ACrx7mfXW

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

- Keep full @agent-<name> in id field (don't strip @) so it gets inserted into text
- Only strip @ from label field for visual display in badge
- Update agent detection to check for '@agent-' prefix since id now includes @

This ensures the actual text inserted and sent to Claude is @agent-<name>

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed ef67dd8 in 1 minute and 17 seconds. Click for details.
  • Reviewed 41 lines of code in 2 files
  • Skipped 0 files when reviewing.
  • Skipped posting 2 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. humanlayer-wui/src/components/internal/SessionDetail/components/FileMentionNode.tsx:17
  • Draft comment:
    Updated agent-check to use '@agent-' prefix. Ensure that the backend consistently provides IDs with an '@' so that the condition (id.startsWith('@agent-')) works as expected.
  • Reason this comment was not posted:
    Comment looked like it was already resolved.
2. humanlayer-wui/src/components/internal/SessionDetail/components/FuzzyFileMentionList.tsx:215
  • Draft comment:
    For agent selections, the id now keeps the full '@agent-' while the label strips the '@'. Confirm that this behavior is consistent across the mention system to avoid double '@' in rendering.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the PR author to confirm that a specific behavior is consistent across the system. This falls under the rule of not asking the author to confirm their intention or ensure behavior is intended. Therefore, this comment should be removed.

Workflow ID: wflow_Cw4SbaUh8TyYxDXY

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

K-Mistele added a commit that referenced this pull request Oct 14, 2025
The constants api.Global and api.Local were renamed in PR #745 to be
values of the SlashCommandSource type. This updates the integration
tests to use the new constant format.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed b36df9e in 1 minute and 25 seconds. Click for details.
  • Reviewed 35 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 3 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. hld/daemon/daemon_slash_commands_integration_test.go:226
  • Draft comment:
    Using api.SlashCommandSource("global") instead of a raw constant improves type consistency. If possible, use a well-named constant (e.g., api.SlashCommandSourceGlobal) to avoid typos in the literal string.
  • Reason this comment was not posted:
    Comment looked like it was already resolved.
2. hld/daemon/daemon_slash_commands_integration_test.go:250
  • Draft comment:
    Similarly, update the duplicate command test to use api.SlashCommandSource("global"). Consider using a shared constant for the expected source value for clarity.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 30% vs. threshold = 50% The suggestion to use a shared constant is a reasonable code quality improvement. Having the string "global" repeated multiple times could lead to maintenance issues if it needs to change. However, this is a test file, and the string literal makes the test more readable and self-contained. The suggestion is not critical enough to warrant keeping the comment. The comment suggests a valid improvement, but am I being too dismissive of test code quality? Test code is still code that needs to be maintained. While test code quality matters, the current approach using string literals makes the tests more readable and self-documenting. The risk of the "global" string needing to change is low, and the benefit of explicit values in tests often outweighs the DRY principle. Delete the comment. While using a constant is a valid suggestion, the current approach with string literals is acceptable for test code and may even be preferable for readability.
3. hld/daemon/daemon_slash_commands_integration_test.go:308
  • Draft comment:
    The comparisons for both global and local sources now use api.SlashCommandSource("global") and api.SlashCommandSource("local"). For improved maintainability, consider defining and using constants for these source values if available.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% This is a test file, and the change being made is just switching from api.Global to api.SlashCommandSource("global"). The suggestion to use constants could be valid, but without seeing the api package we don't know if these constants already exist. Additionally, since this is a test file, the explicitness of using string literals might actually be preferable for readability. I don't have visibility into the api package to know if constants already exist. The comment might be suggesting something that's already available. Even without seeing the api package, suggesting constants in a test file is less compelling since test code often benefits from being explicit rather than abstract. Delete the comment. While using constants could be valid, we don't have enough context about the api package to know if it's a useful suggestion, and test files often benefit from explicit values.

Workflow ID: wflow_3Au5M0A9OZMrqery

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@K-Mistele K-Mistele force-pushed the kyle/eng-2136-agent-should-fuzzy-find-agents-show-them-like-in-claude-cli branch from b36df9e to ef67dd8 Compare October 14, 2025 04:09
The integration tests were still using the old api.Global and api.Local
constants which were renamed to api.SlashCommandSourceGlobal and
api.SlashCommandSourceLocal in the API generation update.

This was causing CI failures while tests passed locally due to cached
or outdated generated files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed e3f52dd in 57 seconds. Click for details.
  • Reviewed 35 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 3 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. hld/daemon/daemon_slash_commands_integration_test.go:226
  • Draft comment:
    Good use of the new api.SlashCommandSourceGlobal constant here instead of the deprecated api.Global. This update improves consistency with the API spec.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
2. hld/daemon/daemon_slash_commands_integration_test.go:250
  • Draft comment:
    The duplicate command test now correctly asserts the global source using api.SlashCommandSourceGlobal. Ensure all duplicate checks follow this updated convention.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
3. hld/daemon/daemon_slash_commands_integration_test.go:308
  • Draft comment:
    Updated conditional checks to use api.SlashCommandSourceGlobal and api.SlashCommandSourceLocal instead of the old constants. This enhances consistency across the tests.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None

Workflow ID: wflow_pKOh29u5rSokCJ8b

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@K-Mistele K-Mistele merged commit 0c70be3 into main Oct 14, 2025
8 of 9 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.

3 participants