Files
cleveragents-core/features/actor_v3_route_synthesis.feature
hurui200320 caf146e132
CI / benchmark-publish (push) Failing after 39s
CI / helm (push) Successful in 38s
CI / build (push) Successful in 54s
CI / lint (push) Successful in 1m2s
CI / push-validation (push) Successful in 21s
CI / quality (push) Successful in 1m26s
CI / typecheck (push) Successful in 1m46s
CI / security (push) Successful in 1m51s
CI / integration_tests (push) Successful in 4m16s
CI / unit_tests (push) Successful in 4m56s
CI / e2e_tests (push) Successful in 4m56s
CI / docker (push) Successful in 1m49s
CI / coverage (push) Successful in 10m51s
CI / status-check (push) Successful in 3s
CI / benchmark-publish (pull_request) Has been skipped
CI / coverage (pull_request) Successful in 14m50s
CI / docker (pull_request) Successful in 1m58s
CI / quality (pull_request) Successful in 1m18s
CI / e2e_tests (pull_request) Successful in 3m53s
CI / integration_tests (pull_request) Successful in 6m34s
CI / unit_tests (pull_request) Successful in 8m47s
CI / push-validation (pull_request) Successful in 20s
CI / lint (pull_request) Successful in 1m19s
CI / typecheck (pull_request) Successful in 1m26s
CI / security (pull_request) Successful in 1m31s
CI / helm (pull_request) Successful in 36s
CI / build (pull_request) Successful in 43s
CI / status-check (pull_request) Successful in 5s
fix(actor): resolve provider from explicit field in v3 YAML before inferring from model
Two bugs prevented built-in LLM actors from working with models that lack a '/'
separator (e.g. claude-sonnet-4-20250514):

1. _generate_builtin_actor_yaml (actor/registry.py) was constructing the model
   field as '{provider}/{model}' (e.g. 'anthropic/claude-sonnet-4-20250514').
   The Anthropic API expects just the bare model ID, causing 404 errors. Fixed
   by using the bare model identifier and lowercasing the provider field to
   match ProviderType enum values.

2. _build_from_v3 (reactive/config_parser.py) always inferred the provider from
   the model string via infer_provider_from_model(). For models without a '/'
   separator this returned 'custom', an invalid ProviderType, causing
   'Unknown provider type: custom' at runtime. Fixed by checking for an
   explicit top-level 'provider' field in the v3 YAML data (per spec resolution
   order step 2) before falling back to inference.

As a side effect, these fixes also resolve issue #10861: agents actor run now
successfully invokes the LLM when using built-in actors. The @tdd_expected_fail
tag has been removed from features/tdd_actor_run_response.feature accordingly.

New BDD scenarios added to features/builtin_actor_v3_yaml.feature and
features/actor_v3_route_synthesis.feature validate both fixes and the fallback
inference behaviour for models with '/' separators.

All quality gates pass: lint, typecheck, 671 feature files (15673 scenarios),
1997 Robot integration tests, coverage 97.12%.

ISSUES CLOSED: #10926
2026-04-30 02:05:12 +00:00

134 lines
6.6 KiB
Gherkin

Feature: v3 actor config parser synthesises execution routes
As a developer using v3 actor YAML configs
I want ReactiveConfigParser to automatically create graph routes for agents
So that run_single_shot() can invoke the LLM instead of silently returning empty
# --- Fix A: _build_from_v3() route synthesis for type:llm / type:tool --------
@tdd_issue @tdd_issue_10807
Scenario: v3 flat LLM actor build produces non-empty routes
Given a flat v3 LLM actor config for route synthesis
When I build the flat v3 config through ReactiveConfigParser
Then the reactive config routes should not be empty
And the reactive config should have exactly one route
And the synthesised route should be a graph route
And the synthesised route entry point should be the router
@tdd_issue @tdd_issue_10807
Scenario: v3 flat tool actor build produces non-empty routes
Given a flat v3 tool actor config for route synthesis
When I build the flat v3 config through ReactiveConfigParser
Then the reactive config routes should not be empty
And the reactive config should have exactly one route
And the synthesised route should be a graph route
@tdd_issue @tdd_issue_10807
Scenario: v3 flat LLM route has router-plus-actor graph structure
Given a flat v3 LLM actor config for route synthesis
When I build the flat v3 config through ReactiveConfigParser
Then the synthesised route should have exactly two nodes
And the synthesised route should have a message router node
And the synthesised route node should reference the actor name
And the synthesised route should have an edge to end
# --- Fix B: _build() route synthesis for nested actors: map format -----------
@tdd_issue @tdd_issue_10807
Scenario: Nested actors map format produces non-empty routes
Given a nested actors map config with cleveragents version 3
When I build the nested actors config through ReactiveConfigParser
Then the reactive config routes should not be empty
And the reactive config should have exactly one route
And the synthesised route should be a graph route
@tdd_issue @tdd_issue_10807
Scenario: Nested actors map uses default_actor for route actor node
Given a nested actors map config with default_actor set
When I build the nested actors config through ReactiveConfigParser
Then the synthesised route should target the default actor
@tdd_issue @tdd_issue_10807
Scenario: Nested actors map without default_actor uses first agent
Given a nested actors map config without default_actor
When I build the nested actors config through ReactiveConfigParser
Then the reactive config routes should not be empty
And the synthesised route should target the first agent
# --- Fix C: nested actors: map translates actor key to provider/model -------
@tdd_issue @tdd_issue_10807
Scenario: Nested actors map with actor key infers provider and model
Given a nested actors map config with actor key "anthropic/claude-sonnet-4-5"
When I build the nested actors config through ReactiveConfigParser
Then the agent config should have provider "anthropic"
And the agent config should have model "claude-sonnet-4-5"
@tdd_issue @tdd_issue_10807
Scenario: Nested actors map with actor key without slash sets model only
Given a nested actors map config with actor key "gpt-4"
When I build the nested actors config through ReactiveConfigParser
Then the agent config should have model "gpt-4"
And the agent config should not have provider set
@tdd_issue @tdd_issue_10807
Scenario: Nested actors map with explicit provider keeps it unchanged
Given a nested actors map config with explicit provider "openai" and model "gpt-4o"
When I build the nested actors config through ReactiveConfigParser
Then the agent config should have provider "openai"
And the agent config should have model "gpt-4o"
# --- Existing route configs are not affected --------------------------------
@tdd_issue @tdd_issue_10807
Scenario: Config with explicit routes does not get extra synthesised routes
Given a config with agents and explicit routes
When I build the explicit routes config through ReactiveConfigParser
Then the reactive config should have exactly one route
And the route should be the explicitly defined one
# --- End-to-end: run_single_shot with synthesised route ---------------------
@tdd_issue @tdd_issue_10807
Scenario: run_single_shot returns non-empty output with synthesised v3 LLM route
Given a ReactiveCleverAgentsApp configured from a flat v3 LLM config
When I call run_single_shot with a test prompt
Then the result should be non-empty
@tdd_issue @tdd_issue_10807
Scenario: run_single_shot returns non-empty output with nested actors map config
Given a ReactiveCleverAgentsApp configured from a nested actors map config
When I call run_single_shot with a test prompt
Then the result should be non-empty
# --- v3 graph actors still work (regression guard) --------------------------
@tdd_issue @tdd_issue_10807
Scenario: v3 graph actor build still produces routes as before
Given a v3 graph actor config dict with route for regression check
When I build the v3 graph config through ReactiveConfigParser
Then the reactive config routes should not be empty
And the reactive config should have exactly one route
# --- Fix: _build_from_v3 respects explicit provider field (issue #10926) ---
@tdd_issue @tdd_issue_10926
Scenario: v3 actor with explicit provider field uses it without inference
Given a flat v3 LLM actor config with explicit provider and model without slash
When I build the flat v3 config through ReactiveConfigParser
Then the agent config should have provider "anthropic"
And the agent config should have model "claude-sonnet-4-20250514"
@tdd_issue @tdd_issue_10926
Scenario: v3 actor without explicit provider falls back to inference from model with slash
Given a flat v3 LLM actor config with model containing slash and no explicit provider
When I build the flat v3 config through ReactiveConfigParser
Then the agent config should have provider "openrouter"
And the agent config should have model "openrouter/anthropic-claude-sonnet"
@tdd_issue @tdd_issue_10926
Scenario: v3 actor with model without slash and no explicit provider gets custom provider
Given a flat v3 LLM actor config with model without slash and no explicit provider
When I build the flat v3 config through ReactiveConfigParser
Then the agent config should have provider "custom"
And the agent config should have model "gpt-4-turbo"