[AUTO-ARCH-14] docs(spec): clarify Anonymous Tool enforcement rules in glossary #9241

Merged
HAL9000 merged 4 commits from auto-arch-14/spec-anonymous-tool-enforcement into master 2026-06-03 04:39:44 +00:00
4 changed files with 14 additions and 7 deletions
+1
View File
@@ -6,6 +6,7 @@ Changed `wf10_batch.robot` to be less likely to create files, and
`plan_generation_graph.robot` to give more test answers.
## [Unreleased]
- **fix(plan): NamespacedName digit-start validation** (#2145, #2147): `NamespacedName` field validators now reject `namespace` and `name` components whose first character is a digit, raising `pydantic.ValidationError` with message `"must start with a letter"`. BDD constructor scenarios updated to use the `"a Pydantic ValidationError should be raised"` step so the assertion correctly matches the exception type raised by Pydantic model construction.
- **fix(cli/plan): plan correct JSON output envelope fix and BDD test coverage** (#8584 / PR #8662): Restructured `agents plan correct --format json` output to nest correction fields under `data.correction` (e.g., `data.correction.mode`) and populate the spec-required CLI envelope with `command="plan correct"`, `status`, `exit_code`, `timing`, and `messages` fields. Added three BDD scenarios in `features/tdd_plan_correct_json_output.feature` validating the envelope structure for both revert and append modes.
- **fix(cli): add --url flag to resource add for git resource type** (#6322): Added support for the `--url` flag on `agents resource add git` command, allowing users to specify a remote URL for git resources. The flag is validated to only apply to git resource types. Includes Behave BDD tests in `features/resource_cli_git_url_flag.feature` and Robot Framework integration tests verifying correct URL validation and CLI behavior.
- **Session create JSON envelope** (#6441): Fixed `agents session create --format json` returning a flat `data` dict instead of the spec-required nested structure with `data.session`, `data.settings`, and `data.actor_details` sub-objects. The `command` field is now populated correctly. Extended JSON envelope coverage to `agents session list`, `show`, `delete --format json`, `export --output-format json`, and `import --format json` so all session commands emit a structured `messages[].text` field (`"0 sessions listed"`, `"Session details loaded"`, `"Session deleted"`, `"Export completed"`, `"Import completed"`).
+2 -2
View File
@@ -132,13 +132,13 @@ The following standards are integrated into the architecture:
???+ abstract "Tools & Skills"
Tool
: The ==atomic unit of execution==: a namespaced, independently registered callable operation. Defined by JSON Schema inputs/outputs, capability metadata (`read_only`, `writes`, `checkpointable`), and a four-stage lifecycle (`discover` / `activate` / `execute` / `deactivate`). Sources: MCP servers, Agent Skills folders, built-ins, or custom Python. Namespaced as `[[server:]namespace/]name`.
: The ==atomic unit of execution==: a namespaced, independently registered callable operation. Defined by JSON Schema inputs/outputs, capability metadata (`read_only`, `writes`, `checkpointable`), and a four-stage lifecycle (`discover` / `activate` / `execute` / `deactivate`). Sources: MCP servers, Agent Skills folders, built-ins, or custom Python. Namespaced as `[[server:]namespace/]name`. Note: The namespacing requirement applies only to registered tools. Anonymous tools use a context-local short name without a namespace prefix.
Validation
: A Tool subtype adding: a `mode` (`required` | `informational`) controlling whether failure blocks execution; a structured JSON return with mandatory `passed` boolean, optional `data`, and optional `message`. ==Always read-only== (`writes = false`, `checkpointable = false`). May wrap an existing Tool via `wraps` + `transform`. Managed via `agents validation add/attach/detach`; always attached to a resource, optionally scoped to a project or plan.
Anonymous Tool
: An inline tool definition embedded in a skill YAML or actor graph node. Same schema as a named tool but unregistered, unnamespaced, and scoped only to its defining context.
: An inline tool definition embedded in a skill YAML or actor graph node. Same schema as a named tool but **unregistered** (never passed to `ToolRegistry.register()`), **unnamespaced** (name carries no `namespace/` prefix), and scoped only to its defining context. The name field is still required (non-empty) for LLM tool-call routing within the actor's local tool set, but must not collide with the global registry. Anonymous tools use a context-local short name (e.g., the bare function name or a skill-scoped identifier). Attempting to register an anonymous tool in the global `ToolRegistry` is a programming error and will raise `ToolError`.
Skill
: A composable, namespaced collection of tools assembled by referencing named tools, defining inline anonymous tools, including other skills, or exposing MCP server tools and Agent Skills ([AgentSkills.io](https://AgentSkills.io)) tools. Actors reference skills by name to acquire capabilities. Namespaced as `[[server:]namespace/]name`.
@@ -6,22 +6,22 @@ Feature: NamespacedName validation
# TDD for issue #2145/#2147: Names must start with a letter
# ---------------------------------------------------------------
@tdd_issue @tdd_issue_2145 @tdd_issue_2147 @tdd_expected_fail
@tdd_issue @tdd_issue_2145 @tdd_issue_2147
Scenario: NamespacedName.parse() rejects namespace starting with a digit
When I parse the namespaced name "123abc/my-action" expecting an error
Then a ValueError should be raised
And the error message should contain "must start with a letter"
@tdd_issue @tdd_issue_2145 @tdd_issue_2147 @tdd_expected_fail
@tdd_issue @tdd_issue_2145 @tdd_issue_2147
Scenario: NamespacedName constructor rejects name starting with a digit
When I construct a NamespacedName with namespace "local" and name "123-action" expecting an error
Then a ValidationError should be raised
Then a Pydantic ValidationError should be raised
And the error message should contain "must start with a letter"
@tdd_issue @tdd_issue_2145 @tdd_issue_2147 @tdd_expected_fail
@tdd_issue @tdd_issue_2145 @tdd_issue_2147
Scenario: NamespacedName constructor rejects namespace starting with a digit
When I construct a NamespacedName with namespace "999org" and name "valid-name" expecting an error
Then a ValidationError should be raised
Then a Pydantic ValidationError should be raised
And the error message should contain "must start with a letter"
# ---------------------------------------------------------------
@@ -231,6 +231,9 @@ class NamespacedName(BaseModel):
# Namespace should be lowercase alphanumeric with hyphens
if not all(c.isalnum() or c == "-" for c in v):
raise ValueError("Namespace must be alphanumeric with hyphens only")
# Namespace must start with a letter, not a digit
if v[0].isdigit():
raise ValueError(f"Namespace {v!r} must start with a letter, not a digit")
return v.lower()
@field_validator("name")
@@ -239,6 +242,9 @@ class NamespacedName(BaseModel):
"""Validate name format (kebab-case recommended)."""
if not v.replace("-", "").replace("_", "").isalnum():
raise ValueError("Name must be alphanumeric with hyphens or underscores")
# Name must start with a letter, not a digit
if v[0].isdigit():
raise ValueError(f"Name {v!r} must start with a letter, not a digit")
return v.lower()
@classmethod