Skip to content

feat: allow runExperiment to accept a VoltOpsClient directly#970

Merged
omeraplak merged 1 commit into
mainfrom
feat/update-voltops-client-evals
Jan 20, 2026
Merged

feat: allow runExperiment to accept a VoltOpsClient directly#970
omeraplak merged 1 commit into
mainfrom
feat/update-voltops-client-evals

Conversation

@omeraplak

@omeraplak omeraplak commented Jan 20, 2026

Copy link
Copy Markdown
Member

PR Checklist

Please check if your PR fulfills the following requirements:

Bugs / Features

What is the current behavior?

What is the new behavior?

fixes (issue)

Notes for reviewers


Summary by cubic

Allow runExperiment to accept a VoltOpsClient directly for cloud dataset resolution and telemetry, so you don’t need to initialize a separate REST client. Docs and examples updated to show the new usage.

  • New Features

    • Accepts VoltOpsClient or VoltOpsRestClient via voltOpsClient.
    • Automatically adapts the client to resolve cloud datasets when a dataset id/name is provided.
    • Updated docs and examples to use VoltOpsClient in offline and overview guides.
  • Refactors

    • Introduced VoltOpsDatasetClient interface and a type guard for dataset clients.
    • Centralized client coercion and dataset resolver attachment in runExperiment.

Written for commit 61cee96. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • runExperiment now accepts an optional voltOpsClient parameter in the configuration object, enabling direct dataset resolution.
  • Documentation

    • Updated examples and guides demonstrating the new voltOpsClient configuration option for offline evaluations.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot

changeset-bot Bot commented Jan 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 61cee96

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@voltagent/evals Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Jan 20, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This change extends the runExperiment API to accept an optional voltOpsClient parameter in the configuration object, enabling direct injection of a VoltOpsClient for dataset resolution. The implementation introduces internal utilities for client normalization and coercion, while introducing a new VoltOpsDatasetClient interface to abstract dataset operations, and updates examples and documentation to reflect the new usage pattern.

Changes

Cohort / File(s) Summary
API Configuration & Implementation
packages/evals/src/experiment/run-experiment.ts, .changeset/clear-signs-cry.md
Adds support for optional voltOpsClient field in runExperiment options. Introduces internal utilities (normalizeClientOption, extractVoltOpsClientOptions, coerceVoltOpsDatasetClient) for client normalization and coercion. Updates attachVoltOpsDatasetResolver to use coerced dataset client.
Type System & Abstractions
packages/evals/src/voltops/dataset.ts
Introduces new VoltOpsDatasetClient interface with three methods (resolveDatasetVersionId, getDataset, listDatasetItems). Replaces VoltOpsRestClient dependencies with VoltOpsDatasetClient across multiple option/parameter types. Adds isVoltOpsDatasetClient type guard function.
Usage Examples & Documentation
examples/with-offline-evals/src/index.ts, website/evaluation-docs/offline-evaluations.md, website/evaluation-docs/overview.md
Demonstrates new voltOpsClient injection pattern in examples. Updates documentation to show VoltOpsClient import (from @voltagent/core or @voltagent/sdk) and instantiation in code examples, replacing previous VoltOpsRestClient references.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A client now hops through config gates,
VoltOps dataset datasets await,
With coercion and type guards so neat,
Injection makes resolution complete,
Dataset dreams become fully real! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main feature change: allowing runExperiment to accept a VoltOpsClient directly, which aligns with the primary objective reflected in all modified files.
Description check ✅ Passed The description covers key sections from the template including checklist items, new features, and refactoring details. However, the current behavior section is empty, new behavior lacks specific detail, and the issue reference placeholder remains unfilled.

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

✨ Finishing touches
  • 📝 Generate docstrings

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

@ghost

This comment has been minimized.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 6 files

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying voltagent with  Cloudflare Pages  Cloudflare Pages

Latest commit: 61cee96
Status: ✅  Deploy successful!
Preview URL: https://87ab11a2.voltagent.pages.dev
Branch Preview URL: https://feat-update-voltops-client-e.voltagent.pages.dev

View logs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
website/evaluation-docs/offline-evaluations.md (1)

253-272: Align VoltOpsClient import with evaluation documentation standard.

Line 264 imports from @voltagent/sdk, but evaluation-docs/overview.md uses @voltagent/core. While both work (@voltagent/sdk re-exports the core version), import from @voltagent/core for consistency across evaluation docs.

🤖 Fix all issues with AI agents
In @.changeset/clear-signs-cry.md:
- Around line 7-18: Replace the import source for VoltOpsClient to match the
codebase pattern: change the module specifier used in the import that declares
VoltOpsClient (the same symbol referenced when creating voltOpsClient passed
into runExperiment with experiment) from "@voltagent/sdk" to "@voltagent/core"
so the file imports VoltOpsClient from the canonical package used elsewhere.

In `@website/evaluation-docs/overview.md`:
- Around line 102-110: The import of VoltOpsClient in this doc uses the wrong
package: change the import source for VoltOpsClient (and any sibling imports in
this snippet such as runExperiment if applicable) from "@voltagent/core" to
"@voltagent/sdk" so it matches the other evaluation-docs (live-evaluations.md,
offline-evaluations.md); update the import line that references VoltOpsClient to
use the `@voltagent/sdk` package and verify the example still resolves.
🧹 Nitpick comments (2)
examples/with-offline-evals/src/index.ts (1)

1-13: Clarify VoltOpsClient initialization in the example.

Line 12 constructs new VoltOpsClient({}); if the client doesn’t default to environment credentials, this example won’t connect. Consider passing VOLTAGENT_PUBLIC_KEY/SECRET_KEY or add a note about env defaults. Also confirm the correct package (@voltagent/core vs @voltagent/sdk) and keep the example aligned with docs.

packages/evals/src/experiment/run-experiment.ts (1)

612-691: Throw a clear error when voltOpsClient is provided but fails to coerce with VoltOps dataset references.

When a client is passed to attachVoltOpsDatasetResolver but doesn't match the expected shape for dataset resolution, the error is silent—coerceVoltOpsDatasetClient returns undefined and the descriptor is returned unchanged. If the descriptor has VoltOps identifiers (id, name, or versionId), this likely indicates the user intended VoltOps resolution, making the silent failure confusing.

The suggested guard improves error visibility: when both voltOpsClient and a VoltOps dataset reference are present but coercion fails, throw a clear error instead of silently returning the unresolved descriptor.

♻️ Optional guard to surface a clearer error
   const datasetClient = coerceVoltOpsDatasetClient(voltOpsClient);
   if (!datasetClient) {
+    if (voltOpsClient && (descriptor.id || descriptor.name || descriptor.versionId)) {
+      throw new Error(
+        "voltOpsClient does not support dataset resolution; pass a VoltOpsRestClient or VoltOpsDatasetClient.",
+      );
+    }
     return descriptor;
   }

Comment on lines +7 to +18
```ts
import { VoltOpsClient } from "@voltagent/sdk";
import { runExperiment } from "@voltagent/evals";
import experiment from "./experiments/support-nightly.experiment";

const voltOpsClient = new VoltOpsClient({
publicKey: process.env.VOLTAGENT_PUBLIC_KEY,
secretKey: process.env.VOLTAGENT_SECRET_KEY,
});

const result = await runExperiment(experiment, {
voltOpsClient,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Search for VoltOpsClient imports across the codebase
rg "VoltOpsClient" --type ts --type js -A 1 -B 1

Repository: VoltAgent/voltagent

Length of output: 50375


🏁 Script executed:

# Check the changeset file content
cat .changeset/clear-signs-cry.md

Repository: VoltAgent/voltagent

Length of output: 621


🏁 Script executed:

# Look for package.json files to understand exports
fd "package.json" --type f | head -20

Repository: VoltAgent/voltagent

Length of output: 906


🏁 Script executed:

# Search for `@voltagent/core` and `@voltagent/sdk` imports to see patterns
rg "from ['\"]@voltagent/(sdk|core)" --type ts --type js -A 0 -B 0

Repository: VoltAgent/voltagent

Length of output: 38161


Update the VoltOpsClient import to use @voltagent/core.

The changeset uses @voltagent/sdk, but the codebase pattern—particularly the with-offline-evals example which is most comparable to this evals feature—imports VoltOpsClient from @voltagent/core. For consistency, change:

import { VoltOpsClient } from "@voltagent/sdk";

to:

import { VoltOpsClient } from "@voltagent/core";

Both packages export the same class, but @voltagent/core is the canonical source and the consistent pattern across the codebase.

🤖 Prompt for AI Agents
In @.changeset/clear-signs-cry.md around lines 7 - 18, Replace the import source
for VoltOpsClient to match the codebase pattern: change the module specifier
used in the import that declares VoltOpsClient (the same symbol referenced when
creating voltOpsClient passed into runExperiment with experiment) from
"@voltagent/sdk" to "@voltagent/core" so the file imports VoltOpsClient from the
canonical package used elsewhere.

Comment on lines 102 to 110
```ts title="Node script"
import { VoltOpsRestClient } from "@voltagent/sdk";
import { VoltOpsClient } from "@voltagent/core";
import { runExperiment } from "@voltagent/evals";
import experiment from "./experiments/support-nightly.experiment";

const voltOpsClient = new VoltOpsRestClient({
const voltOpsClient = new VoltOpsClient({
publicKey: process.env.VOLTAGENT_PUBLIC_KEY,
secretKey: process.env.VOLTAGENT_SECRET_KEY,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's check the file in question
cd website && cat -n evaluation-docs/overview.md | sed -n '100,115p'

Repository: VoltAgent/voltagent

Length of output: 694


🏁 Script executed:

# Search for all VoltOpsClient imports/usages across the entire repo
rg "VoltOpsClient" -A 1 -B 1

Repository: VoltAgent/voltagent

Length of output: 50378


🏁 Script executed:

# Search for package definitions or exports related to VoltOpsClient
rg "export.*VoltOpsClient" -g "*.ts" -g "*.js" -g "*.d.ts"

Repository: VoltAgent/voltagent

Length of output: 1313


🏁 Script executed:

# Check for package.json files that might define exports
find . -name "package.json" -type f | head -20

Repository: VoltAgent/voltagent

Length of output: 946


Align VoltOpsClient import with sibling evaluation-docs files.

Line 103 imports from @voltagent/core, but other files in evaluation-docs/ (live-evaluations.md, offline-evaluations.md) import from @voltagent/sdk. Choose one pattern consistently across the evaluation-docs folder to avoid confusion.

🤖 Prompt for AI Agents
In `@website/evaluation-docs/overview.md` around lines 102 - 110, The import of
VoltOpsClient in this doc uses the wrong package: change the import source for
VoltOpsClient (and any sibling imports in this snippet such as runExperiment if
applicable) from "@voltagent/core" to "@voltagent/sdk" so it matches the other
evaluation-docs (live-evaluations.md, offline-evaluations.md); update the import
line that references VoltOpsClient to use the `@voltagent/sdk` package and verify
the example still resolves.

@omeraplak
omeraplak merged commit ed6075a into main Jan 20, 2026
23 checks passed
@omeraplak
omeraplak deleted the feat/update-voltops-client-evals branch January 20, 2026 17:23
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.

1 participant