ToolCallingAgent silently skips inline-defined skill tools; extend _build_tool_registry() to support them #11222

Open
opened 2026-05-15 05:37:01 +00:00 by hurui200320 · 0 comments
Member

Metadata

Commit Message: feat(actor-run): support inline skill tools in ToolCallingAgent tool registry
Branch: feature/m3-tool-calling-inline-tools

Background and Context

When a skill is resolved in ReactiveCleverAgentsApp._resolve_skills(), each
ResolvedToolEntry is either:

  • Named reference (is_inline=False): name is a registered tool name
    such as "builtin/file-read", looked up in _builtin_registry.
  • Inline definition (is_inline=True): the full tool definition is embedded
    in the inline_tool: SkillInlineTool field of the entry.

ToolCallingAgent._build_tool_registry() — introduced in #11211 — only handles
named references. When is_inline=True, the entry's name is a generated key
that does not exist in _builtin_registry, so get() returns None and the
tool is warned about and silently skipped:

WARNING: tool 'local/my-skill/custom-formatter' not found in builtin registry — skipping
(inline/MCP tools not yet supported in actor run tool-calling path)

This means any skill that defines its tools inline cannot be used with
agents actor run --skill, even though inline tools are entirely valid per
the spec.

Expected Behavior

When _build_tool_registry() encounters an entry with is_inline=True, it
should construct a ToolSpec directly from the inline_tool definition and
register it into the local registry — no _builtin_registry lookup needed.
The resulting tool must pass through the same SEC1 safety constraints that
govern inline tools elsewhere in the codebase (named-operation registry only;
raw code blocks rejected unconditionally).

Named-reference entries (is_inline=False) are unaffected.

Acceptance Criteria

  • A skill with an inline tool definition (is_inline=True, containing
    name, description, input_schema, and a safe named operation) results
    in a ToolSpec being registered in the per-run local ToolRegistry.
  • The LLM receives the inline tool's schema (via export_tool_schemas())
    when --skill is attached to an actor that references a skill with inline tools.
  • Inline tools with a code block are rejected with a StreamRoutingError
    consistent with the SEC1 policy already enforced by SimpleToolAgent.
  • Named-reference tools (is_inline=False) continue to work as before —
    no regression.
  • All existing actor run BDD scenarios continue to pass.

Supporting Information

Relevant code locations:

  • src/cleveragents/reactive/tool_agent.pyToolCallingAgent._build_tool_registry()
    is where the inline branch needs to be added.
  • src/cleveragents/reactive/stream_router.pySimpleToolAgent._SAFE_OPERATIONS
    and the SEC1 code-block rejection are the reference for inline tool safety.
  • src/cleveragents/domain/models/core/skill.pyResolvedToolEntry and
    SkillInlineTool define the inline data model.
  • src/cleveragents/tool/runtime.pyToolSpec is what needs to be constructed.

Introduced as follow-on to #11211.

Subtasks

  • Inspect SkillInlineTool schema to confirm available fields (name,
    description, input_schema, operation, etc.).
  • In _build_tool_registry(), add an is_inline branch: when
    entry.get("is_inline") is True, build a ToolSpec whose handler is
    looked up from SimpleToolAgent._SAFE_OPERATIONS via the entry's operation
    field; reject entries containing a code key with StreamRoutingError (SEC1).
  • Ensure inline entries use the name from the entry dict as ToolSpec.name
    (no _builtin_registry lookup).
  • Deduplicate inline entries via the existing seen set.
  • Write BDD scenarios:
    (A) inline tool with valid operation is registered and callable via the loop;
    (B) inline tool with code block raises StreamRoutingError;
    (C) skill mixing inline and named-reference tools resolves both correctly.
  • Verify coverage ≥ 96.5% via nox -s coverage_report.
  • Run nox (all default sessions), fix any errors.

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • A Git commit is created where the first line of the commit message
    matches the Commit Message in Metadata exactly, followed by a blank line,
    then additional lines providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in
    Metadata exactly.
  • The commit is submitted as a pull request to master, reviewed, and
    merged before this issue is marked done.
## Metadata ``` Commit Message: feat(actor-run): support inline skill tools in ToolCallingAgent tool registry Branch: feature/m3-tool-calling-inline-tools ``` ## Background and Context When a skill is resolved in `ReactiveCleverAgentsApp._resolve_skills()`, each `ResolvedToolEntry` is either: - **Named reference** (`is_inline=False`): `name` is a registered tool name such as `"builtin/file-read"`, looked up in `_builtin_registry`. - **Inline definition** (`is_inline=True`): the full tool definition is embedded in the `inline_tool: SkillInlineTool` field of the entry. `ToolCallingAgent._build_tool_registry()` — introduced in #11211 — only handles named references. When `is_inline=True`, the entry's `name` is a generated key that does not exist in `_builtin_registry`, so `get()` returns `None` and the tool is warned about and silently skipped: ``` WARNING: tool 'local/my-skill/custom-formatter' not found in builtin registry — skipping (inline/MCP tools not yet supported in actor run tool-calling path) ``` This means any skill that defines its tools inline cannot be used with `agents actor run --skill`, even though inline tools are entirely valid per the spec. ## Expected Behavior When `_build_tool_registry()` encounters an entry with `is_inline=True`, it should construct a `ToolSpec` directly from the `inline_tool` definition and register it into the local registry — no `_builtin_registry` lookup needed. The resulting tool must pass through the same SEC1 safety constraints that govern inline tools elsewhere in the codebase (named-operation registry only; raw `code` blocks rejected unconditionally). Named-reference entries (`is_inline=False`) are unaffected. ## Acceptance Criteria - [ ] A skill with an inline tool definition (`is_inline=True`, containing `name`, `description`, `input_schema`, and a safe named `operation`) results in a `ToolSpec` being registered in the per-run local `ToolRegistry`. - [ ] The LLM receives the inline tool's schema (via `export_tool_schemas()`) when `--skill` is attached to an actor that references a skill with inline tools. - [ ] Inline tools with a `code` block are rejected with a `StreamRoutingError` consistent with the SEC1 policy already enforced by `SimpleToolAgent`. - [ ] Named-reference tools (`is_inline=False`) continue to work as before — no regression. - [ ] All existing `actor run` BDD scenarios continue to pass. ## Supporting Information Relevant code locations: - `src/cleveragents/reactive/tool_agent.py` — `ToolCallingAgent._build_tool_registry()` is where the inline branch needs to be added. - `src/cleveragents/reactive/stream_router.py` — `SimpleToolAgent._SAFE_OPERATIONS` and the SEC1 `code`-block rejection are the reference for inline tool safety. - `src/cleveragents/domain/models/core/skill.py` — `ResolvedToolEntry` and `SkillInlineTool` define the inline data model. - `src/cleveragents/tool/runtime.py` — `ToolSpec` is what needs to be constructed. Introduced as follow-on to #11211. ## Subtasks - [ ] Inspect `SkillInlineTool` schema to confirm available fields (`name`, `description`, `input_schema`, `operation`, etc.). - [ ] In `_build_tool_registry()`, add an `is_inline` branch: when `entry.get("is_inline")` is `True`, build a `ToolSpec` whose handler is looked up from `SimpleToolAgent._SAFE_OPERATIONS` via the entry's `operation` field; reject entries containing a `code` key with `StreamRoutingError` (SEC1). - [ ] Ensure inline entries use the `name` from the entry dict as `ToolSpec.name` (no `_builtin_registry` lookup). - [ ] Deduplicate inline entries via the existing `seen` set. - [ ] Write BDD scenarios: (A) inline tool with valid `operation` is registered and callable via the loop; (B) inline tool with `code` block raises `StreamRoutingError`; (C) skill mixing inline and named-reference tools resolves both correctly. - [ ] Verify coverage ≥ 96.5% via `nox -s coverage_report`. - [ ] Run `nox` (all default sessions), fix any errors. ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done.
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#11222
No description provided.