*** Settings ***
Documentation    Integration tests for actor add CLI v3 schema validation
Resource         ${CURDIR}/common.resource
Suite Setup      Setup Test Environment With Database Isolation
Suite Teardown   Cleanup Test Environment

*** Variables ***
${HELPER}    ${CURDIR}/helper_actor_add_v3_schema_validation.py

*** Test Cases ***
Register Valid v3 LLM Actor Via CLI
    [Documentation]    Register a valid v3 LLM actor via agents actor add
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}valid_llm.yaml
    Create File    ${yaml_file}    name: local/test-llm\ntype: llm\ndescription: Test LLM\nprovider: openai\nmodel: gpt-4\n
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/test-llm    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    0
    Should Contain    ${result.stdout}    actor-add-success

Register Valid v3 TOOL Actor Via CLI
    [Documentation]    Register a valid v3 TOOL actor via agents actor add
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}valid_tool.yaml
    ${yaml_content}=    Catenate    SEPARATOR=\n
    ...    name: local/test-tool
    ...    type: tool
    ...    description: Test TOOL
    ...    provider: openai
    ...    model: gpt-4
    ...    tools:
    ...    ${SPACE}${SPACE}- files/read_file
    Create File    ${yaml_file}    ${yaml_content}
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/test-tool    ${yaml_file}    cwd=${WORKSPACE}
    Should Be Equal As Integers    ${result.rc}    0
    Should Contain    ${result.stdout}    actor-add-success

Register Valid v3 GRAPH Actor Via CLI
    [Documentation]    Register a valid v3 GRAPH actor via agents actor add
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}valid_graph.yaml
    ${yaml_content}=    Catenate    SEPARATOR=\n
    ...    name: local/test-graph
    ...    type: graph
    ...    description: Test GRAPH
    ...    provider: openai
    ...    model: gpt-4
    ...    route:
    ...    ${SPACE}${SPACE}nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- id: node_a
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}type: agent
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}name: Node A
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}description: First node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}config: {}
    ...    ${SPACE}${SPACE}edges: []
    ...    ${SPACE}${SPACE}entry_node: node_a
    ...    ${SPACE}${SPACE}exit_nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- node_a
    Create File    ${yaml_file}    ${yaml_content}
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/test-graph    ${yaml_file}    cwd=${WORKSPACE}
    Should Be Equal As Integers    ${result.rc}    0
    Should Contain    ${result.stdout}    actor-add-success

Reject v3 GRAPH Actor With Cycle In Route
    [Documentation]    Reject v3 GRAPH actor with cycle in route via agents actor add
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}broken_graph_cycle.yaml
    ${yaml_content}=    Catenate    SEPARATOR=\n
    ...    name: local/broken-graph
    ...    type: graph
    ...    description: Graph with cycle
    ...    provider: openai
    ...    model: gpt-4
    ...    route:
    ...    ${SPACE}${SPACE}nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- id: node_a
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}type: agent
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}name: Node A
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}description: First node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}config: {}
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- id: node_b
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}type: agent
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}name: Node B
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}description: Second node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}config: {}
    ...    ${SPACE}${SPACE}edges:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- from_node: node_a
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}to_node: node_b
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- from_node: node_b
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}to_node: node_a
    ...    ${SPACE}${SPACE}entry_node: node_a
    ...    ${SPACE}${SPACE}exit_nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- node_b
    Create File    ${yaml_file}    ${yaml_content}
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/broken-graph    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    1
    Should Contain    ${result.stderr}    cycle

Reject v3 LLM Actor Without Model Field
    [Documentation]    Reject v3 LLM actor without model field via agents actor add
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}invalid_llm_no_model.yaml
    Create File    ${yaml_file}    name: local/no-model-llm\ntype: llm\ndescription: LLM without model\nprovider: openai\n
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/no-model-llm    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    1
    Should Contain    ${result.stderr}    LLM actors require 'model' field

Reject v3 TOOL Actor Without Tools Field
    [Documentation]    Reject v3 TOOL actor without tools field via agents actor add
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}invalid_tool_no_tools.yaml
    Create File    ${yaml_file}    name: local/no-tools-tool\ntype: tool\ndescription: TOOL without tools\nprovider: openai\nmodel: gpt-4\n
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/no-tools-tool    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    1
    Should Contain    ${result.stderr}    TOOL actors require at least one tool

Reject v3 GRAPH Actor Without Route Field
    [Documentation]    Reject v3 GRAPH actor without route field via agents actor add
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}invalid_graph_no_route.yaml
    Create File    ${yaml_file}    name: local/no-route-graph\ntype: graph\ndescription: GRAPH without route\nprovider: openai\nmodel: gpt-4\n
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/no-route-graph    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    1
    Should Contain    ${result.stderr}    GRAPH actors require 'route' field

Reject v3 GRAPH Actor Without Model Field
    [Documentation]    Reject v3 GRAPH actor without model field via agents actor add
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}invalid_graph_no_model.yaml
    ${yaml_content}=    Catenate    SEPARATOR=\n
    ...    name: local/no-model-graph
    ...    type: graph
    ...    description: GRAPH without model
    ...    provider: openai
    ...    route:
    ...    ${SPACE}${SPACE}nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- id: node_a
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}type: agent
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}name: Node A
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}description: First node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}config: {}
    ...    ${SPACE}${SPACE}edges: []
    ...    ${SPACE}${SPACE}entry_node: node_a
    ...    ${SPACE}${SPACE}exit_nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- node_a
    Create File    ${yaml_file}    ${yaml_content}
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/no-model-graph    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    1
    Should Contain    ${result.stderr}    GRAPH actors require 'model' field

Reject v3 Actor With Invalid Type Enum
    [Documentation]    Reject v3 actor with invalid type enum via agents actor add
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}invalid_type.yaml
    Create File    ${yaml_file}    name: local/invalid-type\ntype: invalid_type\ndescription: Invalid type\nprovider: openai\nmodel: gpt-4\n
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/invalid-type    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    1
    Should Contain    ${result.stderr}    Input should be 'llm', 'tool' or 'graph'

Reject v3 Actor With Invalid Context View Enum
    [Documentation]    Reject v3 actor with invalid context_view enum via agents actor add
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}invalid_context_view.yaml
    Create File    ${yaml_file}    name: local/invalid-view\ntype: llm\ndescription: Invalid context_view\nprovider: openai\nmodel: gpt-4\ncontext_view: invalid_view\n
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/invalid-view    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    1
    Should Contain    ${result.stderr}    context_view
    Should Contain    ${result.stderr}    Input should be

Reject v3 GRAPH Actor With Cycle Via Update Command
    [Documentation]    Reject v3 GRAPH actor with cycle via agents actor update
    [Tags]    slow
    # First register a valid v3 GRAPH actor so that the update command can
    # resolve it. The update command calls registry.get_actor(name) before
    # validating the new config — without this step the command aborts with
    # "Actor not found" instead of a cycle validation error.
    ${valid_yaml_file}=    Set Variable    ${TEMPDIR}${/}update_valid_graph.yaml
    ${valid_yaml_content}=    Catenate    SEPARATOR=\n
    ...    name: local/update-test-graph
    ...    type: graph
    ...    description: Valid graph actor for update test setup
    ...    provider: openai
    ...    model: gpt-4
    ...    route:
    ...    ${SPACE}${SPACE}nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- id: node_a
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}type: agent
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}name: Node A
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}description: First node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}config: {}
    ...    ${SPACE}${SPACE}edges: []
    ...    ${SPACE}${SPACE}entry_node: node_a
    ...    ${SPACE}${SPACE}exit_nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- node_a
    Create File    ${valid_yaml_file}    ${valid_yaml_content}
    ${setup_result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/update-test-graph    ${valid_yaml_file}    cwd=${WORKSPACE}
    Log    ${setup_result.stdout}
    Log    ${setup_result.stderr}
    Should Be Equal As Integers    ${setup_result.rc}    0
    # Now attempt the update with a cyclic YAML — should fail with cycle error
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}update_broken_cycle.yaml
    ${yaml_content}=    Catenate    SEPARATOR=\n
    ...    name: local/update-test-graph
    ...    type: graph
    ...    description: Graph with cycle for update test
    ...    provider: openai
    ...    model: gpt-4
    ...    route:
    ...    ${SPACE}${SPACE}nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- id: node_a
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}type: agent
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}name: Node A
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}description: First node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}config: {}
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- id: node_b
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}type: agent
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}name: Node B
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}description: Second node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}config: {}
    ...    ${SPACE}${SPACE}edges:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- from_node: node_a
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}to_node: node_b
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- from_node: node_b
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}to_node: node_a
    ...    ${SPACE}${SPACE}entry_node: node_a
    ...    ${SPACE}${SPACE}exit_nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- node_b
    Create File    ${yaml_file}    ${yaml_content}
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    update    local/update-test-graph    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    1
    Should Contain    ${result.stderr}    cycle

Reject v3 GRAPH Actor With Invalid Node ID
    [Documentation]    Reject v3 GRAPH actor with non-alphanumeric node ID via agents actor add
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}invalid_node_id.yaml
    ${yaml_content}=    Catenate    SEPARATOR=\n
    ...    name: local/bad-node-id
    ...    type: graph
    ...    description: Graph with invalid node ID
    ...    provider: openai
    ...    model: gpt-4
    ...    route:
    ...    ${SPACE}${SPACE}nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- id: "bad!node"
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}type: agent
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}name: Bad Node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}description: Node with invalid ID
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}config: {}
    ...    ${SPACE}${SPACE}edges: []
    ...    ${SPACE}${SPACE}entry_node: "bad!node"
    ...    ${SPACE}${SPACE}exit_nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- "bad!node"
    Create File    ${yaml_file}    ${yaml_content}
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/bad-node-id    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    1
    Should Contain    ${result.stderr}    Node ID must be alphanumeric

Reject v3 TOOL Actor With Unnamespaced Tool Name
    [Documentation]    Reject v3 TOOL actor with unnamespaced tool name via agents actor add
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}unnamespaced_tool.yaml
    ${yaml_content}=    Catenate    SEPARATOR=\n
    ...    name: local/bad-tool-name
    ...    type: tool
    ...    description: TOOL with unnamespaced tool
    ...    provider: openai
    ...    model: gpt-4
    ...    tools:
    ...    ${SPACE}${SPACE}- read_file
    Create File    ${yaml_file}    ${yaml_content}
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/bad-tool-name    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    1
    Should Contain    ${result.stderr}    must be namespaced

Register And Show v3 LLM Actor Via CLI
    [Documentation]    Register a v3 LLM actor and verify it is retrievable via show
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}show_llm.yaml
    Create File    ${yaml_file}    name: local/show-test-llm\ntype: llm\ndescription: Show test LLM\nprovider: openai\nmodel: gpt-4\n
    ${add_result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/show-test-llm    ${yaml_file}    cwd=${WORKSPACE}
    Should Be Equal As Integers    ${add_result.rc}    0
    Should Contain    ${add_result.stdout}    actor-add-success
    ${show_result}=    Run Process    ${PYTHON}    ${HELPER}    show    local/show-test-llm    cwd=${WORKSPACE}
    Log    ${show_result.stdout}
    Log    ${show_result.stderr}
    Should Be Equal As Integers    ${show_result.rc}    0
    Should Contain    ${show_result.stdout}    actor-show-success
    Should Contain    ${show_result.stdout}    llm
    Should Contain    ${show_result.stdout}    gpt-4

Build ReactiveConfig From v3 LLM Actor Config
    [Documentation]    Verify that _build_from_v3() correctly synthesises a ReactiveConfig from a v3 LLM blob
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}build_v3_llm.yaml
    ${yaml_content}=    Catenate    SEPARATOR=\n
    ...    name: local/build-test-llm
    ...    type: llm
    ...    description: Build test LLM
    ...    provider: openai
    ...    model: openai/gpt-4
    ...    system_prompt: You are helpful
    ...    skills:
    ...    ${SPACE}${SPACE}- local/file-ops
    Create File    ${yaml_file}    ${yaml_content}
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    build-v3-config    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    0
    Should Contain    ${result.stdout}    build-v3-config-success

Build ReactiveConfig From v3 GRAPH Actor Config
    [Documentation]    Verify that _build_from_v3() correctly synthesises a ReactiveConfig from a v3 graph blob
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}build_v3_graph.yaml
    ${yaml_content}=    Catenate    SEPARATOR=\n
    ...    name: local/build-test-graph
    ...    type: graph
    ...    description: Build test graph
    ...    provider: openai
    ...    model: gpt-4
    ...    route:
    ...    ${SPACE}${SPACE}nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- id: node_a
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}type: agent
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}name: Node A
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}description: First node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}config: {}
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- id: node_b
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}type: agent
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}name: Node B
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}description: Second node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}config: {}
    ...    ${SPACE}${SPACE}edges:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- from_node: node_a
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}to_node: node_b
    ...    ${SPACE}${SPACE}entry_node: node_a
    ...    ${SPACE}${SPACE}exit_nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- node_b
    Create File    ${yaml_file}    ${yaml_content}
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    build-v3-config    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    0
    Should Contain    ${result.stdout}    build-v3-config-success

Reject v3 GRAPH Actor With Unreachable Node
    [Documentation]    Reject v3 GRAPH actor with unreachable node via agents actor add
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}unreachable_node.yaml
    ${yaml_content}=    Catenate    SEPARATOR=\n
    ...    name: local/unreachable-node
    ...    type: graph
    ...    description: Graph with unreachable node
    ...    provider: openai
    ...    model: gpt-4
    ...    route:
    ...    ${SPACE}${SPACE}nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- id: node_a
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}type: agent
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}name: Entry Node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}description: Entry node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}config: {}
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- id: node_b
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}type: agent
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}name: Exit Node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}description: Exit node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}config: {}
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- id: node_orphan
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}type: agent
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}name: Orphan Node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}description: Unreachable node
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}config: {}
    ...    ${SPACE}${SPACE}edges:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- from_node: node_a
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}to_node: node_b
    ...    ${SPACE}${SPACE}entry_node: node_a
    ...    ${SPACE}${SPACE}exit_nodes:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}- node_b
    Create File    ${yaml_file}    ${yaml_content}
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/unreachable-node    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    1
    Should Contain    ${result.stderr}    unreachable

Register LLM Actor With Nested Actors Map And Combined config.actor Field
    [Documentation]
    ...    Verify that agents actor add accepts spec-compliant YAML using the
    ...    nested actors map format with type at actor-entry level and provider/model
    ...    supplied via the combined config.actor: "provider/model" shorthand.
    ...    This is the regression test for bug #11189.
    [Tags]    slow
    ${yaml_file}=    Set Variable    ${TEMPDIR}${/}nested_combined_actor.yaml
    ${yaml_content}=    Catenate    SEPARATOR=\n
    ...    name: local/nested-combined-llm
    ...    cleveragents:
    ...    ${SPACE}${SPACE}version: "3.0"
    ...    ${SPACE}${SPACE}default_actor: main
    ...    actors:
    ...    ${SPACE}${SPACE}main:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}type: llm
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}config:
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}actor: anthropic/claude-sonnet-4-5
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}system_prompt: "You are a test actor."
    ...    ${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}${SPACE}temperature: 0.3
    Create File    ${yaml_file}    ${yaml_content}
    ${result}=    Run Process    ${PYTHON}    ${HELPER}    add    local/nested-combined-llm    ${yaml_file}    cwd=${WORKSPACE}
    Log    ${result.stdout}
    Log    ${result.stderr}
    Should Be Equal As Integers    ${result.rc}    0
    Should Contain    ${result.stdout}    actor-add-success
    ${show_result}=    Run Process    ${PYTHON}    ${HELPER}    show    local/nested-combined-llm    cwd=${WORKSPACE}
    Log    ${show_result.stdout}
    Log    ${show_result.stderr}
    Should Be Equal As Integers    ${show_result.rc}    0
    Should Contain    ${show_result.stdout}    actor-show-success
    Should Contain    ${show_result.stdout}    anthropic
    Should Contain    ${show_result.stdout}    claude-sonnet-4-5
