UAT: ActorConfigSchema.validate_name() rejects server-qualified actor names (server:namespace/name format) #4697

Open
opened 2026-04-08 18:02:08 +00:00 by HAL9000 · 0 comments
Owner

Bug Report

Feature Area: Namespace management and naming conventions — Actor YAML schema
Severity: Medium — spec-required server:namespace/name format rejected at YAML parse time
Discovered by: UAT tester (uat-ns-mgmt-001)


Summary

ActorConfigSchema.validate_name() in src/cleveragents/actor/schema.py enforces exactly one / separator in actor names. This means server-qualified actor names like prod:myorg/my-actor are rejected at YAML schema validation time with a ValidationError, before they even reach the service layer.

This is a separate issue from #4550 (which covers ActorService._normalize_name()). The YAML schema layer is the first point of failure.


Expected Behavior (from spec)

The spec (docs/specification.md, line 155) defines:

Actor: A YAML-configured conversational unit — either a single LLM/agent or a composed LangGraph of actors and tool nodes. Namespaced as [[server:]namespace/]name.

The spec's NamespacedName.parse() in domain/models/core/plan.py correctly handles server:namespace/name:

# "prod:myorg/my-action" -> server="prod", namespace="myorg", name="my-action"
if ":" in name:
    server, name = name.split(":", 1)
if "/" in name:
    namespace, name = name.split("/", 1)

An actor YAML file with name: prod:myorg/my-actor should be valid.


Actual Behavior

Code location: src/cleveragents/actor/schema.py, lines 776–800

@field_validator("name")
@classmethod
def validate_name(cls, v: str) -> str:
    """Ensure actor name follows namespace/name format."""
    if "/" not in v:
        msg = f"Actor name must be namespaced (namespace/name): {v}"
        raise ValueError(msg)

    # Check for exactly one slash
    parts = v.split("/")
    if len(parts) != 2:
        msg = (
            f"Actor name must be namespaced with exactly one slash "
            f"(namespace/name): {v}"
        )
        raise ValueError(msg)

    namespace, name = parts
    if not namespace or not name:
        msg = (
            f"Actor name must be namespaced with non-empty namespace and name: {v}"
        )
        raise ValueError(msg)

    return v

For prod:myorg/my-actor:

  • "/" not in v → False (passes)
  • v.split("/")["prod:myorg", "my-actor"]len(parts) == 2 → passes
  • namespace = "prod:myorg", name = "my-actor" → both non-empty → passes

Wait — actually prod:myorg/my-actor has exactly one /, so it would pass the count check. But prod:myorg would be treated as the namespace (containing a colon), which is semantically wrong.

The real problem: The validator does not parse the server qualifier before checking the namespace/name split. For a name like prod:myorg/my-actor:

  • The validator accepts it (one /)
  • But namespace = "prod:myorg" — a namespace containing a colon is invalid
  • The validator does NOT validate that the namespace part is free of colons

Additionally, for a name like prod:myorg/sub/my-actor (hypothetical multi-slash):

  • v.split("/")["prod:myorg", "sub", "my-actor"]len(parts) == 3rejected

The validator should first strip the server qualifier (prod:) before checking the slash count.


Concrete Failure Case

from cleveragents.actor.schema import ActorConfigSchema

# This YAML is spec-valid but the schema validator mishandles it:
yaml_content = """
name: prod:myorg/my-actor
type: llm
description: A remote actor
model: gpt-4
"""
# ActorConfigSchema.model_validate(yaml.safe_load(yaml_content))
# Results in namespace="prod:myorg" — a namespace with a colon, which is wrong.
# No error is raised but the name is semantically malformed.

The validator silently accepts prod:myorg as a namespace (colon included), which will cause downstream failures when the name is used for lookups.


Fix Required

Update validate_name() to correctly parse the server qualifier before validating the namespace/name structure:

@field_validator("name")
@classmethod
def validate_name(cls, v: str) -> str:
    """Ensure actor name follows [[server:]namespace/]name format."""
    remaining = v
    
    # Strip server qualifier if present
    if ":" in remaining:
        server_part, remaining = remaining.split(":", 1)
        if not server_part:
            raise ValueError(f"Actor name has empty server qualifier: {v}")
    
    if "/" not in remaining:
        raise ValueError(f"Actor name must include namespace/name: {v}")
    
    parts = remaining.split("/")
    if len(parts) != 2:
        raise ValueError(
            f"Actor name must have exactly one '/' after server qualifier: {v}"
        )
    
    namespace, name = parts
    if not namespace or not name:
        raise ValueError(
            f"Actor name must have non-empty namespace and name: {v}"
        )
    
    return v

Metadata

Commit Message: fix(actor): support server:namespace/name format in ActorConfigSchema.validate_name()
Branch Name: fix/actor-schema-server-qualified-name

Subtasks

  • Update ActorConfigSchema.validate_name() to parse server qualifier before slash check
  • Add Behave tests for server-qualified actor names in YAML
  • Verify prod:myorg/my-actor is correctly parsed and stored
  • Verify all nox stages pass

Definition of Done

  • ActorConfigSchema.model_validate({"name": "prod:myorg/my-actor", ...}) succeeds
  • ActorConfigSchema.model_validate({"name": "local/my-actor", ...}) still works
  • All existing tests pass

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

## Bug Report **Feature Area:** Namespace management and naming conventions — Actor YAML schema **Severity:** Medium — spec-required `server:namespace/name` format rejected at YAML parse time **Discovered by:** UAT tester (uat-ns-mgmt-001) --- ## Summary `ActorConfigSchema.validate_name()` in `src/cleveragents/actor/schema.py` enforces exactly one `/` separator in actor names. This means server-qualified actor names like `prod:myorg/my-actor` are rejected at YAML schema validation time with a `ValidationError`, before they even reach the service layer. This is a separate issue from #4550 (which covers `ActorService._normalize_name()`). The YAML schema layer is the first point of failure. --- ## Expected Behavior (from spec) The spec (`docs/specification.md`, line 155) defines: > **Actor**: A YAML-configured conversational unit — either a single LLM/agent or a composed LangGraph of actors and tool nodes. Namespaced as `[[server:]namespace/]name`. The spec's `NamespacedName.parse()` in `domain/models/core/plan.py` correctly handles `server:namespace/name`: ```python # "prod:myorg/my-action" -> server="prod", namespace="myorg", name="my-action" if ":" in name: server, name = name.split(":", 1) if "/" in name: namespace, name = name.split("/", 1) ``` An actor YAML file with `name: prod:myorg/my-actor` should be valid. --- ## Actual Behavior **Code location:** `src/cleveragents/actor/schema.py`, lines 776–800 ```python @field_validator("name") @classmethod def validate_name(cls, v: str) -> str: """Ensure actor name follows namespace/name format.""" if "/" not in v: msg = f"Actor name must be namespaced (namespace/name): {v}" raise ValueError(msg) # Check for exactly one slash parts = v.split("/") if len(parts) != 2: msg = ( f"Actor name must be namespaced with exactly one slash " f"(namespace/name): {v}" ) raise ValueError(msg) namespace, name = parts if not namespace or not name: msg = ( f"Actor name must be namespaced with non-empty namespace and name: {v}" ) raise ValueError(msg) return v ``` For `prod:myorg/my-actor`: - `"/" not in v` → False (passes) - `v.split("/")` → `["prod:myorg", "my-actor"]` → `len(parts) == 2` → passes - `namespace = "prod:myorg"`, `name = "my-actor"` → both non-empty → passes Wait — actually `prod:myorg/my-actor` has exactly one `/`, so it would pass the count check. But `prod:myorg` would be treated as the namespace (containing a colon), which is semantically wrong. **The real problem:** The validator does not parse the server qualifier before checking the namespace/name split. For a name like `prod:myorg/my-actor`: - The validator accepts it (one `/`) - But `namespace = "prod:myorg"` — a namespace containing a colon is invalid - The validator does NOT validate that the namespace part is free of colons Additionally, for a name like `prod:myorg/sub/my-actor` (hypothetical multi-slash): - `v.split("/")` → `["prod:myorg", "sub", "my-actor"]` → `len(parts) == 3` → **rejected** The validator should first strip the server qualifier (`prod:`) before checking the slash count. --- ## Concrete Failure Case ```python from cleveragents.actor.schema import ActorConfigSchema # This YAML is spec-valid but the schema validator mishandles it: yaml_content = """ name: prod:myorg/my-actor type: llm description: A remote actor model: gpt-4 """ # ActorConfigSchema.model_validate(yaml.safe_load(yaml_content)) # Results in namespace="prod:myorg" — a namespace with a colon, which is wrong. # No error is raised but the name is semantically malformed. ``` The validator silently accepts `prod:myorg` as a namespace (colon included), which will cause downstream failures when the name is used for lookups. --- ## Fix Required Update `validate_name()` to correctly parse the server qualifier before validating the namespace/name structure: ```python @field_validator("name") @classmethod def validate_name(cls, v: str) -> str: """Ensure actor name follows [[server:]namespace/]name format.""" remaining = v # Strip server qualifier if present if ":" in remaining: server_part, remaining = remaining.split(":", 1) if not server_part: raise ValueError(f"Actor name has empty server qualifier: {v}") if "/" not in remaining: raise ValueError(f"Actor name must include namespace/name: {v}") parts = remaining.split("/") if len(parts) != 2: raise ValueError( f"Actor name must have exactly one '/' after server qualifier: {v}" ) namespace, name = parts if not namespace or not name: raise ValueError( f"Actor name must have non-empty namespace and name: {v}" ) return v ``` --- ## Metadata **Commit Message:** `fix(actor): support server:namespace/name format in ActorConfigSchema.validate_name()` **Branch Name:** `fix/actor-schema-server-qualified-name` ### Subtasks - [ ] Update `ActorConfigSchema.validate_name()` to parse server qualifier before slash check - [ ] Add Behave tests for server-qualified actor names in YAML - [ ] Verify `prod:myorg/my-actor` is correctly parsed and stored - [ ] Verify all nox stages pass ### Definition of Done - [ ] `ActorConfigSchema.model_validate({"name": "prod:myorg/my-actor", ...})` succeeds - [ ] `ActorConfigSchema.model_validate({"name": "local/my-actor", ...})` still works - [ ] All existing tests pass --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: uat-tester
HAL9000 added this to the v3.5.0 milestone 2026-04-08 18:05:36 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

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