Skip to content

feat: add agents configuration layer with backward-compatible api: migration#228

Merged
asamal4 merged 3 commits into
lightspeed-core:mainfrom
rioloc:feat/agents-config-layer
May 13, 2026
Merged

feat: add agents configuration layer with backward-compatible api: migration#228
asamal4 merged 3 commits into
lightspeed-core:mainfrom
rioloc:feat/agents-config-layer

Conversation

@rioloc
Copy link
Copy Markdown
Collaborator

@rioloc rioloc commented Apr 30, 2026

Summary

Introduces a generic agents: configuration block in system.yaml that makes the HTTP API one agent type among potentially many (e.g., Kubernetes CRD agents for Openshift Agentic Lightspeed). This is the foundational configuration layer — the driver interface and CRD implementation will follow in subsequent PRs.

  • New Pydantic models: AgentsConfig, AgentDefaultConfig, HttpApiAgentConfig in core/models/agents.py
  • SystemConfig gains agents: Optional[AgentsConfig] with auto-migration from api: via model_validator
  • EvaluationData gains agent and agent_config optional fields for per-conversation-group agent selection
  • 3-level per-key agent_config merge: default.agent_config < agents.<name>.agent_config < eval_data.agent_config
  • enabled lives at the AgentsConfig level (not per-agent), with SystemConfig.api_enabled property for backward-compatible access
  • Zero breakage: all existing config.api.* access paths, YAML files, and tests continue working unchanged

Architecture

graph TD
    subgraph "system.yaml"
        API["api:<br/>(existing, preserved)"]
        AGENTS["agents:<br/>(new)"]
    end

    subgraph "SystemConfig"
        API_FIELD["api: APIConfig<br/>(unchanged)"]
        AGENTS_FIELD["agents: Optional[AgentsConfig]<br/>(new)"]
        MIGRATION["model_validator<br/>migrate_api_to_agents"]
        API_ENABLED["api_enabled property<br/>(agents.enabled → api.enabled fallback)"]
    end

    API -->|"loaded by ConfigLoader"| API_FIELD
    API -->|"auto-migrates when<br/>agents: absent"| MIGRATION
    MIGRATION --> AGENTS_FIELD
    AGENTS -->|"loaded by ConfigLoader"| AGENTS_FIELD

    subgraph "AgentsConfig"
        ENABLED["enabled: bool<br/>(agents-level toggle)"]
        DEFAULT["default:<br/>AgentDefaultConfig<br/>(agent selection + agent_config)"]
        HTTP["http_api:<br/>HttpApiAgentConfig"]
        FUTURE["kubernetes_crd:<br/>(future)"]
    end

    AGENTS_FIELD --> ENABLED
    AGENTS_FIELD --> DEFAULT
    AGENTS_FIELD --> HTTP
    AGENTS_FIELD -.-> FUTURE

    subgraph "eval_data.yaml"
        CG1["conversation_group<br/>(no agent = uses default)"]
        CG2["conversation_group<br/>agent: ols_api<br/>agent_config: {timeout: 1200}"]
    end

    subgraph "Config Resolution (per-key merge)"
        RESOLVE["resolve_agent_config()"]
        P1["1. default.agent_config<br/>(lowest priority)"]
        P2["2. agents.&lt;name&gt;.agent_config"]
        P3["3. eval_data.agent_config<br/>(highest priority)"]
    end

    CG2 --> RESOLVE
    P1 --> RESOLVE
    P2 --> RESOLVE
    P3 --> RESOLVE
Loading

3-Level agent_config Merge

Each level provides an agent_config: dict with per-key merge in ascending priority order. Higher levels override matching keys; non-overlapping keys from lower levels survive:

# system.yaml
agents:
  enabled: true
  default:
    agent: ols_api
    agent_config:                    # Level 1 (lowest)
      timeout: 900
      provider: aws
      num_retries: 3
  ols_api:
    type: http_api
    api_base: http://localhost:8080
    agent_config:                    # Level 2
      timeout: 500
      provider: azure
# eval_data.yaml
agent_config:                        # Level 3 (highest)
  timeout: 300

Result: {timeout: 300, provider: azure, num_retries: 3}

Backward Compatibility: api: to agents: Migration

Existing system.yaml files with only an api: block require no changes. A model_validator(mode="before") on SystemConfig auto-migrates the api: data into the new agents: structure at load time, while preserving the original api field for all downstream code.

Existing config (unchanged, continues to work):

# system.yaml — no modifications needed
api:
  enabled: true
  api_base: http://localhost:8080
  timeout: 300
  provider: openai
  model: gpt-4o

What the framework sees internally after auto-migration:

# api: field preserved as-is (config.api.* still works)
api:
  enabled: true
  api_base: http://localhost:8080
  timeout: 300

# agents: field auto-populated by model_validator
agents:
  enabled: true              # hoisted from api.enabled
  default:
    agent: http_api          # enabled=true -> default agent set
  http_api:
    type: http_api
    api_base: http://localhost:8080
    timeout: 300
    provider: openai
    model: gpt-4o

When api.enabled: false:

agents:
  enabled: false             # hoisted from api.enabled
  default:
    agent: null              # no default agent
  http_api:
    type: http_api
    # ... fields still available if explicitly selected

Key Design Decisions

Decision Choice Rationale
enabled at AgentsConfig level Yes Single toggle for all agent-based API calls; api_enabled property provides backward-compat access
Generic agent_config: dict Yes Aligns all 3 levels (default, agent, eval_data); avoids field-specific merge logic
Per-key merge (not replacement) Yes Higher levels override matching keys; non-overlapping keys from lower levels survive
Keep api field on SystemConfig Yes All downstream code reads config.api.* — no breaking changes
Migration location model_validator(mode="before") Handles both YAML (dict) and programmatic (APIConfig instance) paths
extra="forbid" on AgentsConfig Flat YAML parsed via model_validator Catches typos; agent names extracted into typed agents dict

Files Changed

File Change
core/models/agents.py AgentsConfig (with enabled), AgentDefaultConfig (with agent_config), HttpApiAgentConfig (with agent_config), resolve_agent_config() 3-level merge
core/models/system.py Add agents field, migration validators, api_enabled property
core/models/data.py Add agent, agent_config fields to EvaluationData
core/constants.py Add DEFAULT_AGENT_TYPE, SUPPORTED_AGENT_TYPES
core/system/loader.py Pass agents YAML data through to SystemConfig
core/models/__init__.py Export new models
pipeline/evaluation/pipeline.py Use config.api_enabled
pipeline/evaluation/processor.py Use config.api_enabled
pipeline/evaluation/evaluator.py Use config.api_enabled
runner/evaluation.py Use system_config.api_enabled
tests/**/test_agents.py 25 tests for agent config models, 3-level merge resolution
tests/**/test_system.py 11 migration + api_enabled property tests
tests/**/test_loader.py 2 loader integration tests
tests/**/test_data.py 4 EvaluationData agent field tests

Test plan

  • All agent config model tests pass (defaults, merge, resolution, validation)
  • All migration tests pass (enabled/disabled, dict/instance, skip when agents present)
  • All loader tests pass (YAML with agents block, api-only auto-migration)
  • All EvaluationData agent field tests pass
  • Full test suite: 915 passed, 0 failed — zero regressions
  • make pre-commit passes (bandit, check-types, pyright, docstyle, ruff, pylint, black)

Design Reference

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Flexible agent configuration system with HTTP API agents
    • Per-conversation agent selection and per-conversation config overrides
    • Optional MCP header–based authentication for agents
    • Configurable agent timeouts, retries and endpoint types
    • Automatic migration from legacy API config to the new agent model
    • Unified agents enablement flag respected across evaluation flows
  • Tests

    • Added extensive unit and integration tests covering agent configs, migration, and runtime behavior

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds agent configuration models and resolution; integrates optional SystemConfig.agents with legacy api→agents migration; exposes per-conversation agent and agent_config on EvaluationData; updates runtime gating to use agents presence/enabled; and adds tests for parsing, validation, resolution, migration, and runtime usage.

Changes

Agent Configuration and Selection System

Layer / File(s) Summary
Constants
src/lightspeed_evaluation/core/constants.py
Defines DEFAULT_AGENT_TYPE = "http_api" and SUPPORTED_AGENT_TYPES = ["http_api"].
Model exports
src/lightspeed_evaluation/core/models/__init__.py
Imports and re-exports agent model types: AgentDefaultConfig, AgentsConfig, HttpApiAgentConfig, MCPHeadersConfig, MCPServerConfig.
MCP auth models
src/lightspeed_evaluation/core/models/agents.py
Adds MCPServerConfig and MCPHeadersConfig with validation requiring configured env vars when enabled.
HTTP API base fields
src/lightspeed_evaluation/core/models/agents.py
Adds HttpApiBaseFields for shared HTTP API settings with endpoint_type validation.
HttpApiAgentConfig & AgentDefinition
src/lightspeed_evaluation/core/models/agents.py
Adds HttpApiAgentConfig (type="http_api") with optional mcp_headers; defines AgentDefinition union.
AgentDefaultConfig
src/lightspeed_evaluation/core/models/agents.py
Adds AgentDefaultConfig for reserved default selection and shared agent_config overrides.
AgentsConfig container & resolution
src/lightspeed_evaluation/core/models/agents.py
Implements AgentsConfig with a before-validator that parses a flat YAML namespace into default + agents, an after-validator enforcing supported type values, and resolve_agent_config() that merges agent_config dictionaries with precedence: default < named agent < explicit override.
EvaluationData additions
src/lightspeed_evaluation/core/models/data.py
Adds optional agent and agent_config fields to EvaluationData for per-conversation agent selection/overrides.
SystemConfig integration & APIConfig refactor
src/lightspeed_evaluation/core/models/system.py
Refactors APIConfig to inherit HttpApiBaseFields; adds optional agents: Optional[AgentsConfig] to SystemConfig, a before-validator to migrate legacy api into agents when absent, and an after-validator to validate agents.default.agent references.
ConfigLoader change
src/lightspeed_evaluation/core/system/loader.py
Forwards top-level agents from YAML into SystemConfig construction.
Runtime usage updates
src/lightspeed_evaluation/pipeline/..., src/lightspeed_evaluation/runner/evaluation.py
Runtime gating for script metrics, API client creation, amended-data saving, DataValidator construction, and token-usage calculation now use presence/enabled state of agents instead of api.enabled.
Tests
tests/unit/core/models/test_agents.py, tests/unit/core/models/test_data.py, tests/unit/core/models/test_system.py, tests/unit/core/system/test_loader.py, tests/unit/runner/test_evaluation.py, tests/integration/test_full_evaluation.py, and related pipeline tests
Adds unit tests for agent models, AgentsConfig parsing and resolution, EvaluationData agent fields, SystemConfig migration, ConfigLoader behavior; updates tests to use AgentsConfig or agents = None for gating.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding a new agents configuration layer with backward-compatible migration from the existing api configuration.
Docstring Coverage ✅ Passed Docstring coverage is 95.33% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@rioloc
Copy link
Copy Markdown
Collaborator Author

rioloc commented Apr 30, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lightspeed_evaluation/core/models/agents.py`:
- Around line 116-123: The code mutates the input with data.pop("default") and
can overwrite previously collected agent entries by assigning agents = value
when encountering the "agents" key; to fix, avoid in-place mutation by reading
default_data = data.get("default", {}) or operate on a shallow copy (e.g., copy
= dict(data)), initialize agents as an empty dict before the loop, and when you
see the "agents" key merge its mapping into the agents dict instead of assigning
(and for flat entries where isinstance(value, dict) and "type" in value, insert
them into agents using a unique key), ensuring you use the existing agents dict
rather than replacing it (referencing variables default_data, agents, and the
loop that iterates over data.items()).

In `@src/lightspeed_evaluation/core/models/data.py`:
- Around line 405-409: The agent Field currently allows whitespace-only strings;
add validation to reject strings that are blank after trimming by adding a
Pydantic validator for the agent field (e.g., `@validator`("agent") or
`@field_validator`) that returns None if input is None but raises a ValueError
when str(value).strip() == "" (with a clear message like "agent must not be
empty or whitespace-only"); update any relevant error text and unit tests that
exercise the Agent resolution flow. Ensure the validator is implemented in the
same model class in data.py where the agent: Optional[str] Field is declared so
whitespace-only values are caught at model validation time.

In `@src/lightspeed_evaluation/core/models/system.py`:
- Around line 877-888: The current migration silently drops legacy API fields
because agent_fields only keeps keys in HttpApiAgentConfig.model_fields; detect
unexpected keys in api_data (for dicts and BaseModel dumps) by computing
unexpected = set(all_keys) - valid_fields - {"enabled"} and, if non-empty, raise
a clear error (e.g., ValueError) or otherwise fail fast with a message listing
the unexpected keys so callers know to update HttpApiAgentConfig or migrate
legacy fields; apply this check in the branches that use api_data, referencing
the variables api_data, valid_fields, agent_fields and
HttpApiAgentConfig.model_fields.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f77ef196-b137-474d-b568-5fbac126e29a

📥 Commits

Reviewing files that changed from the base of the PR and between 8762b7f and c33d395.

📒 Files selected for processing (10)
  • src/lightspeed_evaluation/core/constants.py
  • src/lightspeed_evaluation/core/models/__init__.py
  • src/lightspeed_evaluation/core/models/agents.py
  • src/lightspeed_evaluation/core/models/data.py
  • src/lightspeed_evaluation/core/models/system.py
  • src/lightspeed_evaluation/core/system/loader.py
  • tests/unit/core/models/test_agents.py
  • tests/unit/core/models/test_data.py
  • tests/unit/core/models/test_system.py
  • tests/unit/core/system/test_loader.py

Comment thread src/lightspeed_evaluation/core/models/agents.py
Comment thread src/lightspeed_evaluation/core/models/data.py
Comment thread src/lightspeed_evaluation/core/models/system.py Outdated
@rioloc rioloc force-pushed the feat/agents-config-layer branch from 3f372ff to c0b0678 Compare April 30, 2026 10:41
@rioloc
Copy link
Copy Markdown
Collaborator Author

rioloc commented Apr 30, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@rioloc rioloc force-pushed the feat/agents-config-layer branch 6 times, most recently from cfcd43f to 5ec6b29 Compare May 5, 2026 10:28
@rioloc rioloc marked this pull request as ready for review May 5, 2026 10:36
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
src/lightspeed_evaluation/core/models/agents.py (1)

191-193: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard nested agents merge against non-mapping input.

agents.update(value) assumes value is a mapping. Malformed config (for example, agents: []) will throw a low-level exception during pre-validation instead of a clear config error.

Suggested fix
         for key, value in data.items():
             if key == "agents":
-                agents.update(value)
+                if not isinstance(value, dict):
+                    raise ConfigurationError(
+                        "agents must be a mapping of agent names to definitions"
+                    )
+                agents.update(value)
             elif isinstance(value, dict) and "type" in value:
                 agents[key] = value
             else:
                 remaining[key] = value
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lightspeed_evaluation/core/models/agents.py` around lines 191 - 193, The
merge for the "agents" key currently calls agents.update(value) without ensuring
value is a mapping, which will raise a low-level exception for non-mapping
inputs (e.g., list); update the check in the same block that handles key ==
"agents" to first verify isinstance(value, dict) (or collections.abc.Mapping)
and only call agents.update(value) when true, otherwise raise a clear config
error (e.g., ValueError or ConfigError) indicating that "agents" must be a
mapping; reference the existing "agents" variable and the key == "agents" branch
to locate where to add the guard and the explicit error.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/integration/test_agents_config_compat.py`:
- Around line 48-53: The helper _find_csv currently allows multiple
"*_detailed.csv" files and returns the first, which can hide duplicate-output
regressions; update _find_csv to assert there is exactly one match (e.g. replace
the current truthy assert with a check like assert len(csvs) == 1 and include
the list of found files in the error message) and still return csvs[0];
reference the function name _find_csv and the local variable csvs to locate the
change.
- Around line 55-59: _sorting in _read_scores is currently only by
(conversation_group_id, turn_id) which is unstable when multiple metric rows
exist per turn; update the sort key in _read_scores to include additional
deterministic fields (e.g., metric name/metric_name and any scorer/score_id
fields) or fall back to a deterministic tuple of the remaining row values (e.g.,
tuple(r[k] for k in sorted(r.keys()) if k not in
("conversation_group_id","turn_id"))) so rows with the same group/turn are
ordered reproducibly; change the key lambda in _read_scores accordingly to use
those extra fields for stable ordering.

---

Duplicate comments:
In `@src/lightspeed_evaluation/core/models/agents.py`:
- Around line 191-193: The merge for the "agents" key currently calls
agents.update(value) without ensuring value is a mapping, which will raise a
low-level exception for non-mapping inputs (e.g., list); update the check in the
same block that handles key == "agents" to first verify isinstance(value, dict)
(or collections.abc.Mapping) and only call agents.update(value) when true,
otherwise raise a clear config error (e.g., ValueError or ConfigError)
indicating that "agents" must be a mapping; reference the existing "agents"
variable and the key == "agents" branch to locate where to add the guard and the
explicit error.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f462bfd8-0aed-4f72-9fca-d34395fdf749

📥 Commits

Reviewing files that changed from the base of the PR and between c33d395 and 5ec6b29.

📒 Files selected for processing (15)
  • src/lightspeed_evaluation/core/constants.py
  • src/lightspeed_evaluation/core/models/.agents.py.swp
  • src/lightspeed_evaluation/core/models/__init__.py
  • src/lightspeed_evaluation/core/models/agents.py
  • src/lightspeed_evaluation/core/models/data.py
  • src/lightspeed_evaluation/core/models/system.py
  • src/lightspeed_evaluation/core/system/loader.py
  • tests/integration/agents_config/eval_data.yaml
  • tests/integration/agents_config/system_agents.yaml
  • tests/integration/agents_config/system_legacy_api.yaml
  • tests/integration/test_agents_config_compat.py
  • tests/unit/core/models/test_agents.py
  • tests/unit/core/models/test_data.py
  • tests/unit/core/models/test_system.py
  • tests/unit/core/system/test_loader.py
✅ Files skipped from review due to trivial changes (2)
  • src/lightspeed_evaluation/core/constants.py
  • src/lightspeed_evaluation/core/system/loader.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/lightspeed_evaluation/core/models/init.py
  • tests/unit/core/models/test_agents.py
  • tests/unit/core/models/test_system.py
  • tests/unit/core/system/test_loader.py
  • src/lightspeed_evaluation/core/models/data.py
  • tests/unit/core/models/test_data.py

Comment thread tests/integration/test_agents_config_compat.py Outdated
Comment thread tests/integration/test_agents_config_compat.py Outdated
@rioloc rioloc force-pushed the feat/agents-config-layer branch 2 times, most recently from 974ba94 to a53c4a4 Compare May 7, 2026 09:26
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
tests/unit/core/models/test_data.py (2)

691-698: 💤 Low value

match="String should match pattern" is a brittle pydantic-internal message.

The match= string on line 693 couples the test to pydantic's internal error-message wording, which can change across pydantic minor/patch releases. The sibling test_empty_agent_name_rejected (line 684) already omits match=; consider doing the same here, or match on something stable like "agent" (the field name) or the regex pattern itself.

♻️ Suggested fix
-        with pytest.raises(ValidationError, match="String should match pattern"):
+        with pytest.raises(ValidationError):
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/core/models/test_data.py` around lines 691 - 698, The
test_whitespace_agent_name_rejected currently asserts ValidationError with a
brittle pydantic-internal message via match="String should match pattern";
update the pytest.raises call for EvaluationData(agent="   ") to either remove
the match argument (like test_empty_agent_name_rejected) or use a stable matcher
such as match="agent" or the actual regex pattern, so the test asserts a
ValidationError for EvaluationData/TurnData without depending on pydantic's
exact wording.

672-680: 💤 Low value

Missing coverage: agent_config without agent.

All five new tests either set both fields or neither. It's worth adding a test (or a pytest.mark.parametrize case) that provides agent_config without agent to document — and pin — the model's behaviour for that combination (accepted, rejected, or silently ignored).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/core/models/test_data.py` around lines 672 - 680, Add a test case
to explicitly cover the scenario where EvaluationData is instantiated with
agent_config but without agent so the model behavior is pinned; update or add a
new test (e.g., alongside test_agent_config_accepted or as a
pytest.mark.parametrize) that constructs
EvaluationData(conversation_group_id="cg1", agent_config={"timeout":1200},
turns=[TurnData(...)] ) and asserts the expected outcome (accepted and stored in
data.agent_config, or raises a validation error) matching the intended behavior
of the EvaluationData model; reference the EvaluationData class and the
agent_config and agent fields when implementing the assertion so reviewers can
see the documented behaviour.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/unit/core/models/test_data.py`:
- Around line 691-698: The test_whitespace_agent_name_rejected currently asserts
ValidationError with a brittle pydantic-internal message via match="String
should match pattern"; update the pytest.raises call for EvaluationData(agent=" 
") to either remove the match argument (like test_empty_agent_name_rejected) or
use a stable matcher such as match="agent" or the actual regex pattern, so the
test asserts a ValidationError for EvaluationData/TurnData without depending on
pydantic's exact wording.
- Around line 672-680: Add a test case to explicitly cover the scenario where
EvaluationData is instantiated with agent_config but without agent so the model
behavior is pinned; update or add a new test (e.g., alongside
test_agent_config_accepted or as a pytest.mark.parametrize) that constructs
EvaluationData(conversation_group_id="cg1", agent_config={"timeout":1200},
turns=[TurnData(...)] ) and asserts the expected outcome (accepted and stored in
data.agent_config, or raises a validation error) matching the intended behavior
of the EvaluationData model; reference the EvaluationData class and the
agent_config and agent fields when implementing the assertion so reviewers can
see the documented behaviour.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cfd5ea93-0c7a-4047-ae85-9912dae29791

📥 Commits

Reviewing files that changed from the base of the PR and between 5ec6b29 and a53c4a4.

📒 Files selected for processing (11)
  • src/lightspeed_evaluation/core/constants.py
  • src/lightspeed_evaluation/core/models/.agents.py.swp
  • src/lightspeed_evaluation/core/models/__init__.py
  • src/lightspeed_evaluation/core/models/agents.py
  • src/lightspeed_evaluation/core/models/data.py
  • src/lightspeed_evaluation/core/models/system.py
  • src/lightspeed_evaluation/core/system/loader.py
  • tests/unit/core/models/test_agents.py
  • tests/unit/core/models/test_data.py
  • tests/unit/core/models/test_system.py
  • tests/unit/core/system/test_loader.py
✅ Files skipped from review due to trivial changes (3)
  • src/lightspeed_evaluation/core/system/loader.py
  • src/lightspeed_evaluation/core/constants.py
  • tests/unit/core/models/test_system.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/lightspeed_evaluation/core/models/data.py
  • src/lightspeed_evaluation/core/models/system.py
  • src/lightspeed_evaluation/core/models/init.py
  • tests/unit/core/system/test_loader.py
  • tests/unit/core/models/test_agents.py
  • src/lightspeed_evaluation/core/models/agents.py

…gration

Introduce a generic `agents:` configuration block in system.yaml that
makes the HTTP API one agent type among potentially many (e.g., Kubernetes
CRD agents for Openshift Agentic Lightspeed).

The key design ensures zero breakage of existing configs and code:

- New Pydantic models: AgentsConfig, AgentDefaultConfig, HttpApiAgentConfig
  in a new `core/models/agents.py` module
- SystemConfig gains an `agents: Optional[AgentsConfig]` field alongside
  the existing `api:` field
- A model_validator auto-migrates `api:` to `agents:` when `agents:` is
  absent, so all existing system.yaml files continue working unchanged
- `api.enabled=True` maps to `default.agent="http_api"`;
  `api.enabled=False` maps to `default.agent=None`
- The `api` field is preserved — all downstream code reading `config.api`
  continues to work without modification
- EvaluationData gains `agent` and `agent_config` optional fields for
  per-conversation-group agent selection and config overrides
- Config resolution follows a 3-level priority chain:
  eval_data.agent_config > agents.<name> > agents.default
- ConfigLoader passes `agents` YAML data through to SystemConfig

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@asamal4 asamal4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you !! PR looks good; very much aligned with the design doc..
I have couple of suggestions on the yaml structure. WDYT ?

Below will be aligned as per the eval data.

  # Current
  agents:
    default:
      agent: http_api
      timeout: 300
      retry: 3
    http_api:
      type: http_api
      api_base: http://prod
  
  # Proposed
  agents:
    default:
      agent: api
      agent_config:
        timeout: 300
        retry: 3
    api:
      type: http_api
      api_base: http://prod

agent null seems to be not very intuitive for live data disabled mode. Should we have enabled as part of agents.

# Current
agents:
  default:
    agent: null 

# Proposed
agents:
  enabled: false
  default:
    agent: api

Comment thread src/lightspeed_evaluation/core/models/agents.py Outdated
Comment thread src/lightspeed_evaluation/core/models/agents.py Outdated
Comment thread src/lightspeed_evaluation/core/models/data.py Outdated
Comment thread src/lightspeed_evaluation/core/models/system.py
Comment thread src/lightspeed_evaluation/core/models/agents.py
Comment thread src/lightspeed_evaluation/core/models/system.py
Comment thread src/lightspeed_evaluation/core/models/agents.py Outdated
rioloc added a commit to rioloc/lightspeed-evaluation that referenced this pull request May 11, 2026
…nfig layer

- Replace timeout/retry fields with generic agent_config dict on
  AgentDefaultConfig and HttpApiAgentConfig, implementing 3-level
  per-key merge (default < agent < eval_data) in resolve_agent_config
- Move enabled from per-agent (HttpApiAgentConfig) to AgentsConfig level,
  add api_enabled property on SystemConfig for backward-compatible access
- Move whitespace pattern validator from EvaluationData.agent to
  AgentDefaultConfig.agent where agent names are defined as identifiers
- Update endpoint_type description to include infer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
rioloc added a commit to rioloc/lightspeed-evaluation that referenced this pull request May 11, 2026
…nfig layer

- Replace timeout/retry fields with generic agent_config dict on
  AgentDefaultConfig and HttpApiAgentConfig, implementing 3-level
  per-key merge (default < agent < eval_data) in resolve_agent_config
- Move enabled from per-agent (HttpApiAgentConfig) to AgentsConfig level,
  add api_enabled property on SystemConfig for backward-compatible access
- Move whitespace pattern validator from EvaluationData.agent to
  AgentDefaultConfig.agent where agent names are defined as identifiers
- Update endpoint_type description to include infer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rioloc rioloc force-pushed the feat/agents-config-layer branch from 1a09355 to c9e5428 Compare May 11, 2026 15:43
@rioloc
Copy link
Copy Markdown
Collaborator Author

rioloc commented May 11, 2026

@asamal4 I've addressed all the discussed changes in c9e5428

Comment thread src/lightspeed_evaluation/core/models/agents.py
Comment thread src/lightspeed_evaluation/pipeline/evaluation/processor.py Outdated
…nfig layer

- Replace timeout/retry fields with generic agent_config dict on
  AgentDefaultConfig and HttpApiAgentConfig, implementing 3-level
  per-key merge (default < agent < eval_data) in resolve_agent_config
- Move enabled from per-agent (HttpApiAgentConfig) to AgentsConfig level,
  add api_enabled property on SystemConfig for backward-compatible access
- Move whitespace pattern validator from EvaluationData.agent to
  AgentDefaultConfig.agent where agent names are defined as identifiers
- Update endpoint_type description to include infer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rioloc rioloc force-pushed the feat/agents-config-layer branch from c9e5428 to 880f460 Compare May 12, 2026 12:06
…i defaults

_create_api_client now calls AgentsConfig.resolve_agent_config() to
obtain the correct endpoint_type, api_base, and other settings from the
default agent definition. Previously it used config.api directly, which
fell back to legacy defaults (endpoint_type: streaming) even when agents
were explicitly configured with endpoint_type: query.

Widen APIClient config type to accept HttpApiAgentConfig alongside
APIConfig since both share the same HttpApiBaseFields interface.

Per-conversation agent overrides are not yet supported and will be
addressed by the agent driver architecture.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@asamal4 asamal4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks !! LGTM..
Few action items for future:

  1. Let's add a warning when no api/agent is configured
  2. Bug fix for the override (not super critical, as this is the new capability. backward compatibility is to set right default agent)
  3. Documentation (Once we have the full integration)

Copy link
Copy Markdown
Member

@VladimirKadlec VladimirKadlec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thank you.
@asamal4 this is a big change, we have to communicate it clearly to the teams.

See docs/AGENTIC_EVAL.md sections 3.1–3.4 for the full design context.

@rioloc I don't see docs/AGENTIC_EVAL.md anywhere 🤷

@asamal4
Copy link
Copy Markdown
Collaborator

asamal4 commented May 13, 2026

@asamal4 this is a big change, we have to communicate it clearly to the teams.

@VladimirKadlec Agree. We will have to make sure that teams are using right config, before we remove current api: config completely. As of now no impact due to backward compatibility.

@rioloc I edited the description to remove the doc ref.. May be I will add this later, after some clean-up.

@asamal4 asamal4 merged commit f25b262 into lightspeed-core:main May 13, 2026
16 of 17 checks passed
xmican10 pushed a commit to xmican10/lightspeed-evaluation that referenced this pull request May 13, 2026
…gration (lightspeed-core#228)

* feat: add agents configuration layer with backward-compatible api: migration

Introduce a generic `agents:` configuration block in system.yaml that
makes the HTTP API one agent type among potentially many (e.g., Kubernetes
CRD agents for Openshift Agentic Lightspeed).

The key design ensures zero breakage of existing configs and code:

- New Pydantic models: AgentsConfig, AgentDefaultConfig, HttpApiAgentConfig
  in a new `core/models/agents.py` module
- SystemConfig gains an `agents: Optional[AgentsConfig]` field alongside
  the existing `api:` field
- A model_validator auto-migrates `api:` to `agents:` when `agents:` is
  absent, so all existing system.yaml files continue working unchanged
- `api.enabled=True` maps to `default.agent="http_api"`;
  `api.enabled=False` maps to `default.agent=None`
- The `api` field is preserved — all downstream code reading `config.api`
  continues to work without modification
- EvaluationData gains `agent` and `agent_config` optional fields for
  per-conversation-group agent selection and config overrides
- Config resolution follows a 3-level priority chain:
  eval_data.agent_config > agents.<name> > agents.default
- ConfigLoader passes `agents` YAML data through to SystemConfig

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: address PR lightspeed-core#228 review feedback on agents config layer

- Replace timeout/retry fields with generic agent_config dict on
  AgentDefaultConfig and HttpApiAgentConfig, implementing 3-level
  per-key merge (default < agent < eval_data) in resolve_agent_config
- Move enabled from per-agent (HttpApiAgentConfig) to AgentsConfig level,
  add api_enabled property on SystemConfig for backward-compatible access
- Move whitespace pattern validator from EvaluationData.agent to
  AgentDefaultConfig.agent where agent names are defined as identifiers
- Update endpoint_type description to include infer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve default agent config for API client instead of legacy api defaults

_create_api_client now calls AgentsConfig.resolve_agent_config() to
obtain the correct endpoint_type, api_base, and other settings from the
default agent definition. Previously it used config.api directly, which
fell back to legacy defaults (endpoint_type: streaming) even when agents
were explicitly configured with endpoint_type: query.

Widen APIClient config type to accept HttpApiAgentConfig alongside
APIConfig since both share the same HttpApiBaseFields interface.

Per-conversation agent overrides are not yet supported and will be
addressed by the agent driver architecture.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants