Skip to content

[OPIK-7110] [BE] fix: stop capping user-mapped variables on the agentic-tools path#7414

Open
miguelgrc wants to merge 2 commits into
mainfrom
miguelg/OPIK-7110-fix-agentic-tools-variable-mapping
Open

[OPIK-7110] [BE] fix: stop capping user-mapped variables on the agentic-tools path#7414
miguelgrc wants to merge 2 commits into
mainfrom
miguelg/OPIK-7110-fix-agentic-tools-variable-mapping

Conversation

@miguelgrc

Copy link
Copy Markdown
Contributor

Details

On the agentic-tools path, capReplacements() was truncating ALL variable substitutions to 4K chars — including user-mapped scoring variables (output, expected_output). The LLM judge then had to drill down via tools to recover the full values, which was non-deterministic and produced intermittent "Insufficient data" failures for customers with large traces.

  • capReplacements() now accepts an uncappedKeys set: user-mapped variables (trace sections and literals) pass through at full length, while sentinel variables (spans, trace, span) are still capped since the agentic tools are purpose-built to navigate them.
  • Both trace-level and span-level capped prepareLlmRequest overloads use the new selective capping.
  • The old uniform capReplacements(replacements, max, hint) is removed; callers pass Set.of() for uniform capping.

Change checklist

  • User facing
  • Documentation update

Issues

  • OPIK-7110

AI-WATERMARK

AI-WATERMARK: yes

  • Tools: Claude Code (Opus)
  • Model(s): claude-opus-4-6
  • Scope: Implementation, tests, PR description
  • Human verification: Code reviewed, locally tested with reproduction script confirming fix

Testing

  • mvn test -f apps/opik-backend/pom.xml -Dtest=\"OnlineScoringEngineCapReplacementsTest,OnlineScoringEngineTest\" — 108 tests pass, 0 failures
  • mvn spotless:check — passes
  • Local reproduction with repro_opik_7110.py: created an LLM-as-judge rule with output/expected_output variable mappings, logged traces with 240K+ char output (answer buried past the 4K cap mark), confirmed agentic-tools path activates (Trace context exceeds '50000' tokens; switching to agentic-tools mode), and verified:
    • Before fix: non-deterministic results — some traces scored answer_present=[0] (LLM failed to drill down and find the answer)
    • After fix: LLM sees full output directly in the prompt, no tool drill-down needed for scoring data

Documentation

N/A — internal behavioral fix, no API or config changes.

…ic-tools path

On the agentic-tools path, capReplacements() was truncating ALL variable
substitutions to 4K chars — including the user's scoring variables (output,
expected_output). The LLM then had to drill down via tools to recover the
full values, which was non-deterministic and produced intermittent
"Insufficient data" failures.

Now capReplacements() accepts an uncappedKeys set: user-mapped variables
(trace sections and literals) are passed through at full length, while
sentinel variables (spans, trace, span) are still capped since the tools
are purpose-built to navigate them.
@miguelgrc miguelgrc requested a review from a team as a code owner July 9, 2026 11:31
@github-actions github-actions Bot added the java Pull requests that update Java code label Jul 9, 2026
@github-actions github-actions Bot added Backend tests Including test files, or tests related like configuration. labels Jul 9, 2026
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

⏱️ pre-commit per-hook timing

Hook Description Result Duration
🌐 typecheck — frontend Whole-project tsc type check 39.65s
🐳 hadolint — dockerfiles Lint Dockerfiles 13.65s
🌐 eslint — frontend Lint + autofix JS/TS 13.52s
☕ spotless — java backend Format Java code 7.46s
⚓ helm-docs Regenerate Helm chart README 4.64s
🐍 mypy — python sdk Static type check 1.72s
⚙️ actionlint — github workflows Lint GitHub Actions workflows 0.71s
🐍 fix end of files — python sdk Ensure files end in a newline 0.04s
🐍 trim trailing whitespace — python sdk Strip trailing whitespace 0.04s
🛡️ fix end of files — guardrails Ensure files end in a newline 0.03s
🐍 ruff-format — python sdk Format Python code (ruff) 0.02s
🐍 ruff — python sdk Lint + autofix Python (ruff) 0.02s
🛡️ trim trailing whitespace — guardrails Strip trailing whitespace 0.02s
Total (13 ran) 81.52s
⏭️ 28 skipped (no matching files changed)
Hook Description Result
🤖 trim trailing whitespace — optimizer Strip trailing whitespace ⏭️
🤖 fix end of files — optimizer Ensure files end in a newline ⏭️
🤖 check yaml — optimizer Validate YAML syntax ⏭️
🤖 check json — optimizer Validate JSON syntax ⏭️
🤖 check toml — optimizer Validate TOML syntax ⏭️
🤖 check for added large files — optimizer Block large files (>1MB) ⏭️
🔐 detect private key — optimizer Block committed private keys ⏭️
🤖 check for merge conflicts — optimizer Block merge-conflict markers ⏭️
🤖 check for case conflicts — optimizer Block case-only name clashes ⏭️
🤖 pyupgrade — optimizer Modernize Python syntax ⏭️
🤖 ruff — optimizer Lint + autofix Python (ruff) ⏭️
🤖 ruff-format — optimizer Format Python code (ruff) ⏭️
🤖 mypy — optimizer Static type check ⏭️
📓 nbstripout — optimizer notebooks Strip notebook output ⏭️
📝 markdownlint — optimizer Lint Markdown ⏭️
🔤 codespell — optimizer Fix common misspellings ⏭️
📊 radon cc — optimizer Cyclomatic-complexity gate ⏭️
📊 radon raw — optimizer Raw size metrics gate ⏭️
📊 xenon — optimizer Fail on complexity thresholds ⏭️
📊 lizard — optimizer Cyclomatic-complexity gate ⏭️
🧹 vulture — optimizer Find dead code ⏭️
🛡️ ruff — guardrails Lint + autofix Python (ruff) ⏭️
🛡️ ruff-format — guardrails Format Python code (ruff) ⏭️
🛡️ mypy — guardrails Static type check ⏭️
block non-public FE plugins Block non-public FE plugins ⏭️
🧪 pre-commit wrapper smoke tests Self-test the wrapper scripts ⏭️
📘 eslint — typescript sdk Lint + autofix JS/TS ⏭️
📘 typecheck — typescript sdk Whole-project tsc type check ⏭️

online_scoring_agentic_routing_total{path, trigger, workspace_id,
workspace_name} — emitted per evaluation in shouldUseAgenticTools,
tracks agentic vs inline routing by trigger reason and workspace.
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Python SDK E2E Tests Results (Python 3.10)

286 tests  ±0   284 ✅ ±0   5m 42s ⏱️ -1s
  1 suites ±0     2 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 473b41b. ± Comparison against base commit cf7015e.

♻️ This comment has been updated with latest results.

@andrescrz andrescrz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Couple of thoughts, but not blockers.

* sentinel variables (like {@code spans}). Used by {@link #capReplacements} to decide which
* keys to leave uncapped.
*/
static Set<String> userMappedVariableKeys(Map<String, String> variables) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not a blocker: I'd try to test this indirectly through the public methods, instead of unit testing, that should give you enough coverage in most of the cases. But if you still want to unit test this, please annotate it with VisibleForTesting from Guava.

Comment on lines +75 to +76
private static final AttributeKey<String> PATH_KEY = AttributeKey.stringKey("path");
private static final AttributeKey<String> TRIGGER_KEY = AttributeKey.stringKey("trigger");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

These two metric are going to provide a lot of cardinality. Not a blocker, but you should keep an eye to see if this behaves well in production and check that it doesn't overwhelm our telemetry pipeline (collection, ingestion, dashboards etc.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backend java Pull requests that update Java code tests Including test files, or tests related like configuration.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants