UAT: _parse_actor_name() silently defaults bare actor names to openai provider without spec justification #4888

Open
opened 2026-04-08 20:15:28 +00:00 by HAL9000 · 2 comments
Owner

Bug Report

Feature Area: Namespacing — Built-in LLM Actor Provider Prefixes
Tested by: UAT tester instance uat-namespacing

What Was Tested

Code analysis of src/cleveragents/application/services/llm_actors.py — the _parse_actor_name() function used to resolve actor names to LLM provider/model pairs.

Expected Behavior (from spec)

Per the spec's Namespace Rules and the Namespace Types table:

| openai/, anthropic/, etc. | Built-in LLM actors | N/A (built-in) | openai/gpt-4, anthropic/claude-3-opus |

Built-in LLM actors use explicit provider prefixes (openai/, anthropic/, etc.). The spec does not define a "default provider" for bare actor names — all LLM actors must be referenced with their full provider/model namespace.

The spec's glossary entry for Namespace states:

Built-in LLM actors use provider prefixes (e.g., openai/, anthropic/).

This implies the prefix is required, not optional.

Actual Behavior

_parse_actor_name() in llm_actors.py (lines 67–80) silently defaults bare actor names (without /) to the openai provider:

def _parse_actor_name(actor_name: str) -> tuple[str, str]:
    """Split ``provider/model`` into *(provider_type, model_id)*.

    Examples:
        ``openai/gpt-4``     → ``("openai", "gpt-4")``
        ``anthropic/claude-3`` → ``("anthropic", "claude-3")``
        ``gpt-4``             → ``("openai", "gpt-4")``  (default provider)
    """
    if not actor_name:
        return ("openai", "gpt-4")
    parts = actor_name.split("/", 1)
    if len(parts) == 2:
        return (parts[0], parts[1])
    return ("openai", actor_name)  # ← silently assumes openai

This means:

  • gpt-4("openai", "gpt-4") — silently assumes OpenAI
  • claude-3("openai", "claude-3")incorrectly routes to OpenAI instead of Anthropic
  • ""("openai", "gpt-4") — silently uses a hardcoded default

Code Location

  • src/cleveragents/application/services/llm_actors.py, lines 67–80

Impact

  1. Silent misrouting: A user who specifies claude-3 (without the anthropic/ prefix) will have their plan routed to OpenAI's API looking for a model named claude-3, which will fail at runtime with an obscure error rather than a clear "actor not found" message.
  2. Hardcoded default: The fallback to openai/gpt-4 when actor_name is empty is a hardcoded default that bypasses the configured actor.default.strategy and actor.default.execution config keys.
  3. Spec violation: The spec requires explicit provider prefixes for built-in LLM actors. Silently defaulting to OpenAI contradicts this.

Steps to Reproduce

from cleveragents.application.services.llm_actors import _parse_actor_name

# Silently routes to OpenAI — should raise an error or use configured default:
print(_parse_actor_name("claude-3"))  # ("openai", "claude-3") — wrong!
print(_parse_actor_name("gpt-4"))     # ("openai", "gpt-4") — silent assumption
print(_parse_actor_name(""))          # ("openai", "gpt-4") — hardcoded default

Fix

_parse_actor_name() should:

  1. Require the provider/model format — raise a ValidationError for bare names
  2. OR look up the configured default actor from actor.default.strategy/actor.default.execution config keys instead of hardcoding openai/gpt-4
def _parse_actor_name(actor_name: str) -> tuple[str, str]:
    if not actor_name or "/" not in actor_name:
        raise ValidationError(
            f"Actor name '{actor_name}' must use provider/model format "
            "(e.g., 'openai/gpt-4', 'anthropic/claude-3-opus')"
        )
    provider, model = actor_name.split("/", 1)
    return (provider, model)

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: uat-tester

## Bug Report **Feature Area:** Namespacing — Built-in LLM Actor Provider Prefixes **Tested by:** UAT tester instance `uat-namespacing` ### What Was Tested Code analysis of `src/cleveragents/application/services/llm_actors.py` — the `_parse_actor_name()` function used to resolve actor names to LLM provider/model pairs. ### Expected Behavior (from spec) Per the spec's Namespace Rules and the Namespace Types table: > | `openai/`, `anthropic/`, etc. | Built-in LLM actors | N/A (built-in) | `openai/gpt-4`, `anthropic/claude-3-opus` | Built-in LLM actors use **explicit provider prefixes** (`openai/`, `anthropic/`, etc.). The spec does not define a "default provider" for bare actor names — all LLM actors must be referenced with their full `provider/model` namespace. The spec's glossary entry for Namespace states: > Built-in LLM actors use provider prefixes (e.g., `openai/`, `anthropic/`). This implies the prefix is required, not optional. ### Actual Behavior `_parse_actor_name()` in `llm_actors.py` (lines 67–80) silently defaults bare actor names (without `/`) to the `openai` provider: ```python def _parse_actor_name(actor_name: str) -> tuple[str, str]: """Split ``provider/model`` into *(provider_type, model_id)*. Examples: ``openai/gpt-4`` → ``("openai", "gpt-4")`` ``anthropic/claude-3`` → ``("anthropic", "claude-3")`` ``gpt-4`` → ``("openai", "gpt-4")`` (default provider) """ if not actor_name: return ("openai", "gpt-4") parts = actor_name.split("/", 1) if len(parts) == 2: return (parts[0], parts[1]) return ("openai", actor_name) # ← silently assumes openai ``` This means: - `gpt-4` → `("openai", "gpt-4")` — silently assumes OpenAI - `claude-3` → `("openai", "claude-3")` — **incorrectly** routes to OpenAI instead of Anthropic - `""` → `("openai", "gpt-4")` — silently uses a hardcoded default ### Code Location - `src/cleveragents/application/services/llm_actors.py`, lines 67–80 ### Impact 1. **Silent misrouting**: A user who specifies `claude-3` (without the `anthropic/` prefix) will have their plan routed to OpenAI's API looking for a model named `claude-3`, which will fail at runtime with an obscure error rather than a clear "actor not found" message. 2. **Hardcoded default**: The fallback to `openai/gpt-4` when `actor_name` is empty is a hardcoded default that bypasses the configured `actor.default.strategy` and `actor.default.execution` config keys. 3. **Spec violation**: The spec requires explicit provider prefixes for built-in LLM actors. Silently defaulting to OpenAI contradicts this. ### Steps to Reproduce ```python from cleveragents.application.services.llm_actors import _parse_actor_name # Silently routes to OpenAI — should raise an error or use configured default: print(_parse_actor_name("claude-3")) # ("openai", "claude-3") — wrong! print(_parse_actor_name("gpt-4")) # ("openai", "gpt-4") — silent assumption print(_parse_actor_name("")) # ("openai", "gpt-4") — hardcoded default ``` ### Fix `_parse_actor_name()` should: 1. Require the `provider/model` format — raise a `ValidationError` for bare names 2. OR look up the configured default actor from `actor.default.strategy`/`actor.default.execution` config keys instead of hardcoding `openai/gpt-4` ```python def _parse_actor_name(actor_name: str) -> tuple[str, str]: if not actor_name or "/" not in actor_name: raise ValidationError( f"Actor name '{actor_name}' must use provider/model format " "(e.g., 'openai/gpt-4', 'anthropic/claude-3-opus')" ) provider, model = actor_name.split("/", 1) return (provider, model) ``` --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: uat-tester
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: Medium — Silent default to openai provider without spec justification; could cause unexpected behavior
  • Milestone: v3.5.0 (Autonomy Hardening — namespacing)
  • Story Points: 2 — S — Fixing the default provider resolution logic is a small task
  • MoSCoW: Should Have — Correct provider resolution is important for spec compliance but not blocking core functionality
  • Parent Epic: #4947 (Server Implementation Legendary)

Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner

Issue triaged by project owner: - **State**: Verified - **Priority**: Medium — Silent default to openai provider without spec justification; could cause unexpected behavior - **Milestone**: v3.5.0 (Autonomy Hardening — namespacing) - **Story Points**: 2 — S — Fixing the default provider resolution logic is a small task - **MoSCoW**: Should Have — Correct provider resolution is important for spec compliance but not blocking core functionality - **Parent Epic**: #4947 (Server Implementation Legendary) --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner
freemo added this to the v3.5.0 milestone 2026-04-08 23:40:56 +00:00
freemo modified the milestone from v3.5.0 to v3.2.0 2026-04-08 23:42:18 +00:00
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: Medium — _parse_actor_name() silently defaults bare actor names to openai provider
  • Milestone: v3.2.0 — Actor name parsing is core actor functionality (M3 scope)
  • Story Points: 3 — M — Fixing actor name parsing to not silently default to openai
  • MoSCoW: Should Have — Actor name parsing correctness is important for multi-provider support
  • Parent Epic: #357 (Decisions + Validations + Invariants M3)

Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner

Issue triaged by project owner: - **State**: Verified - **Priority**: Medium — `_parse_actor_name()` silently defaults bare actor names to openai provider - **Milestone**: v3.2.0 — Actor name parsing is core actor functionality (M3 scope) - **Story Points**: 3 — M — Fixing actor name parsing to not silently default to openai - **MoSCoW**: Should Have — Actor name parsing correctness is important for multi-provider support - **Parent Epic**: #357 (Decisions + Validations + Invariants M3) --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
cleveragents/cleveragents-core#4888
No description provided.