UAT: ToolCallRouter.route() does not pass linked_resource_types to ToolRunner.execute() — container-routed tools always fail with ContainerUnavailableError #2136

Open
opened 2026-04-03 04:21:30 +00:00 by freemo · 1 comment
Owner

Metadata

  • Branch: fix/tool-router-linked-resource-types
  • Commit Message: fix(tool): pass linked_resource_types from ToolCallRouter to ToolRunner.execute()
  • Milestone: v3.7.0
  • Parent Epic: #392

Background and Context

The ToolCallRouter is the central router that translates LLM provider tool call formats and routes them through the ToolRunner. When a tool is routed to container execution (via plan-level or project-level execution_environment), the ToolRunner.execute() method validates that at least one container resource is linked to the project before delegating to the container executor.

Current Behavior

ToolCallRouter.route() and ToolCallRouter.route_streaming() call self._runner.execute() without passing linked_resource_types:

# In router.py, ToolCallRouter.route():
result = self._runner.execute(
    request.tool_name,
    request.arguments,
    plan_env=self._plan_env,
    project_env=self._project_env,
    # linked_resource_types is NOT passed — defaults to []
)

The ToolRunner.execute() signature includes linked_resource_types: list[str] | None = None, which defaults to [] when not provided. The ExecutionEnvironmentResolver.validate_container_available() then checks this empty list and always raises ContainerUnavailableError.

This means: any tool routed through ToolCallRouter that resolves to container execution will always fail with ContainerUnavailableError, even when the project has container resources (devcontainer-instance, container-instance) properly linked.

Additionally, the ToolCallRouter constructor has no linked_resource_types parameter, so there is no way to pass this information to the router at construction time either.

Expected Behavior

Per the spec §Execution Environment Routing, the 6-level precedence chain should resolve to container execution when appropriate, and the container availability check should use the actual linked resource types for the project. When a project has a devcontainer-instance or container-instance resource linked, container-routed tools should succeed (assuming a ContainerToolExecutor is configured).

The ToolCallRouter should accept linked_resource_types as a constructor parameter and forward it to ToolRunner.execute().

Steps to Reproduce

  1. Create a project with a devcontainer-instance resource linked
  2. Set plan_env="container" on a ToolCallRouter
  3. Route any tool call through the router
  4. Observe: ContainerUnavailableError is raised even though the project has a container resource

Code Location

  • cleveragents.tool.router.ToolCallRouter.__init__() — missing linked_resource_types parameter
  • cleveragents.tool.router.ToolCallRouter.route() — does not pass linked_resource_types to ToolRunner.execute()
  • cleveragents.tool.router.ToolCallRouter.route_streaming() — does not pass linked_resource_types to ToolRunner.execute()
  • cleveragents.tool.runner.ToolRunner.execute() — the linked_resource_types parameter already exists but is never populated by the router

Acceptance Criteria

  • ToolCallRouter.__init__() accepts linked_resource_types: list[str] | None = None
  • ToolCallRouter.route() passes linked_resource_types to ToolRunner.execute()
  • ToolCallRouter.route_streaming() passes linked_resource_types to ToolRunner.execute()
  • Container-routed tools succeed when the project has container resources linked
  • Tests verify the fix

Supporting Information

Verified via code analysis on 2026-04-03. The ToolRunner.execute() signature already supports linked_resource_types — the bug is that ToolCallRouter never passes it. This is a pure wiring bug: the parameter exists on the callee but the caller never supplies it, causing the container availability check to always see an empty resource list and always raise ContainerUnavailableError.

Subtasks

  • Add linked_resource_types: list[str] | None = None parameter to ToolCallRouter.__init__()
  • Store linked_resource_types as self._linked_resource_types in ToolCallRouter.__init__()
  • Pass linked_resource_types=self._linked_resource_types in ToolCallRouter.route() call to self._runner.execute()
  • Pass linked_resource_types=self._linked_resource_types in ToolCallRouter.route_streaming() call to self._runner.execute()
  • Tests (Behave): Add BDD scenarios verifying container-routed tools succeed when linked_resource_types includes devcontainer-instance or container-instance
  • Tests (Behave): Add BDD scenario verifying ContainerUnavailableError is still raised when linked_resource_types is empty and container execution is requested
  • Tests (Robot): Add integration test for end-to-end container tool routing with linked resources
  • Verify coverage ≥97% 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 (fix(tool): pass linked_resource_types from ToolCallRouter to ToolRunner.execute()), 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 (fix/tool-router-linked-resource-types).
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.
  • All nox stages pass.
  • Coverage ≥ 97%.

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-new-issue-creator

## Metadata - **Branch**: `fix/tool-router-linked-resource-types` - **Commit Message**: `fix(tool): pass linked_resource_types from ToolCallRouter to ToolRunner.execute()` - **Milestone**: v3.7.0 - **Parent Epic**: #392 ## Background and Context The `ToolCallRouter` is the central router that translates LLM provider tool call formats and routes them through the `ToolRunner`. When a tool is routed to container execution (via plan-level or project-level `execution_environment`), the `ToolRunner.execute()` method validates that at least one container resource is linked to the project before delegating to the container executor. ## Current Behavior `ToolCallRouter.route()` and `ToolCallRouter.route_streaming()` call `self._runner.execute()` without passing `linked_resource_types`: ```python # In router.py, ToolCallRouter.route(): result = self._runner.execute( request.tool_name, request.arguments, plan_env=self._plan_env, project_env=self._project_env, # linked_resource_types is NOT passed — defaults to [] ) ``` The `ToolRunner.execute()` signature includes `linked_resource_types: list[str] | None = None`, which defaults to `[]` when not provided. The `ExecutionEnvironmentResolver.validate_container_available()` then checks this empty list and always raises `ContainerUnavailableError`. This means: **any tool routed through `ToolCallRouter` that resolves to container execution will always fail with `ContainerUnavailableError`**, even when the project has container resources (`devcontainer-instance`, `container-instance`) properly linked. Additionally, the `ToolCallRouter` constructor has no `linked_resource_types` parameter, so there is no way to pass this information to the router at construction time either. ## Expected Behavior Per the spec §Execution Environment Routing, the 6-level precedence chain should resolve to container execution when appropriate, and the container availability check should use the actual linked resource types for the project. When a project has a `devcontainer-instance` or `container-instance` resource linked, container-routed tools should succeed (assuming a `ContainerToolExecutor` is configured). The `ToolCallRouter` should accept `linked_resource_types` as a constructor parameter and forward it to `ToolRunner.execute()`. ## Steps to Reproduce 1. Create a project with a `devcontainer-instance` resource linked 2. Set `plan_env="container"` on a `ToolCallRouter` 3. Route any tool call through the router 4. Observe: `ContainerUnavailableError` is raised even though the project has a container resource ## Code Location - `cleveragents.tool.router.ToolCallRouter.__init__()` — missing `linked_resource_types` parameter - `cleveragents.tool.router.ToolCallRouter.route()` — does not pass `linked_resource_types` to `ToolRunner.execute()` - `cleveragents.tool.router.ToolCallRouter.route_streaming()` — does not pass `linked_resource_types` to `ToolRunner.execute()` - `cleveragents.tool.runner.ToolRunner.execute()` — the `linked_resource_types` parameter already exists but is never populated by the router ## Acceptance Criteria - [ ] `ToolCallRouter.__init__()` accepts `linked_resource_types: list[str] | None = None` - [ ] `ToolCallRouter.route()` passes `linked_resource_types` to `ToolRunner.execute()` - [ ] `ToolCallRouter.route_streaming()` passes `linked_resource_types` to `ToolRunner.execute()` - [ ] Container-routed tools succeed when the project has container resources linked - [ ] Tests verify the fix ## Supporting Information Verified via code analysis on 2026-04-03. The `ToolRunner.execute()` signature already supports `linked_resource_types` — the bug is that `ToolCallRouter` never passes it. This is a pure wiring bug: the parameter exists on the callee but the caller never supplies it, causing the container availability check to always see an empty resource list and always raise `ContainerUnavailableError`. ## Subtasks - [ ] Add `linked_resource_types: list[str] | None = None` parameter to `ToolCallRouter.__init__()` - [ ] Store `linked_resource_types` as `self._linked_resource_types` in `ToolCallRouter.__init__()` - [ ] Pass `linked_resource_types=self._linked_resource_types` in `ToolCallRouter.route()` call to `self._runner.execute()` - [ ] Pass `linked_resource_types=self._linked_resource_types` in `ToolCallRouter.route_streaming()` call to `self._runner.execute()` - [ ] Tests (Behave): Add BDD scenarios verifying container-routed tools succeed when `linked_resource_types` includes `devcontainer-instance` or `container-instance` - [ ] Tests (Behave): Add BDD scenario verifying `ContainerUnavailableError` is still raised when `linked_resource_types` is empty and container execution is requested - [ ] Tests (Robot): Add integration test for end-to-end container tool routing with linked resources - [ ] Verify coverage ≥97% 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 (`fix(tool): pass linked_resource_types from ToolCallRouter to ToolRunner.execute()`), 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 (`fix/tool-router-linked-resource-types`). - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done. - All nox stages pass. - Coverage ≥ 97%. --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
freemo added this to the v3.7.0 milestone 2026-04-03 04:21:35 +00:00
freemo self-assigned this 2026-04-03 16:58:02 +00:00
Author
Owner

MoSCoW classification: Must Have

Rationale: This issue addresses a core spec requirement or blocks critical functionality. The project cannot ship without this fix.


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

MoSCoW classification: **Must Have** Rationale: This issue addresses a core spec requirement or blocks critical functionality. The project cannot ship without this fix. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
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.

Blocks
#392 Epic: Actor YAML & Compiler
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#2136
No description provided.