Skip to content

camelCaseToKebabCase breaks acronyms in agent names (e.g., AISessionAgent → a-i-session-agent) #351

@markdembo

Description

@markdembo

Problem

The camelCaseToKebabCase function in agents/dist/utils.js treats every capital letter as a word boundary, which breaks common naming conventions that use acronyms (e.g., AI, API, UI, DB).

Expected Behavior

AISessionAgent should convert to ai-session-agent

Actual Behavior

AISessionAgent converts to a-i-session-agent (each letter A, I treated separately)

The Error Message

The url http://localhost/agents/a-i-session-agent/default does not match any server namespace.
Did you forget to add a durable object binding to the class A-i-session-agent in your wrangler.jsonc?

This error is confusing because:

  1. It doesn't explain that the agent name was transformed
  2. It suggests adding a binding for A-i-session-agent (which isn't a valid class name)
  3. Users have no indication that their AISessionAgent class name is causing the mismatch

Workaround

Pass the kebab-case name directly to useAgent():

// Instead of this (broken):
useAgent({ agent: 'AISessionAgent', name: sessionId })

// Do this (works):
useAgent({ agent: 'ai-session-agent', name: sessionId })

This works because camelCaseToKebabCase('ai-session-agent') returns 'ai-session-agent' unchanged.

Suggested Fixes

Option 1: Improve the transformation function

Update camelCaseToKebabCase to handle consecutive capitals as acronyms:

function camelCaseToKebabCase(str) {
  // Handle consecutive capitals as acronyms (e.g., "AI" stays together)
  return str
    .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')  // Split before last capital of acronym
    .replace(/([a-z])([A-Z])/g, '$1-$2')         // Split lowercase to uppercase
    .toLowerCase();
}
// AISessionAgent -> ai-session-agent
// APIEndpoint -> api-endpoint  
// MyUIComponent -> my-ui-component

Option 2: Better error message

If the namespace isn't found, show what the input was transformed to:

Agent namespace 'a-i-session-agent' not found.
Note: 'AISessionAgent' was converted to 'a-i-session-agent'.
Tip: Pass the kebab-case name directly: useAgent({ agent: 'ai-session-agent' })

Option 3: Document the behavior

Add JSDoc to the agent option explaining:

  • The transformation that occurs
  • That kebab-case names pass through unchanged
  • Examples with acronyms

Environment

  • agents package version: 0.0.74
  • hono-agents package version: 0.0.9

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No 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