Skip to content

[Agent Builder] Fix SkillInvoked evaluator matching a retired tool name - #284661

Merged
patrykkopycinski merged 1 commit into
elastic:mainfrom
patrykkopycinski:fix/persona-matrix-skill-invoked-load-skill
Aug 12, 2026
Merged

[Agent Builder] Fix SkillInvoked evaluator matching a retired tool name#284661
patrykkopycinski merged 1 commit into
elastic:mainfrom
patrykkopycinski:fix/persona-matrix-skill-invoked-load-skill

Conversation

@patrykkopycinski

@patrykkopycinski patrykkopycinski commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

The persona-matrix SkillInvoked evaluator matched only
attributes.gen_ai.tool.name == "filestore.read", but the agent loads skills
via the load_skill tool. Verified against the golden cluster over a 7-day
window:

tool name spans (7d)
filestore.read 0
load_skill 7,991

Because total_tool_spans is still non-zero for these traces, the existing
"no tool spans → unavailable" guard does not trip. The evaluator therefore
returned a confident score: 0 instead of null — silently zeroing the
Skill Invoked column for every model in every persona-matrix run, not just
for one model.

This surfaced while generating a matrix column for a model that appeared to
never route into any skill. Trace data showed the opposite: it invoked
load_skill and called security skills directly. The reported zero was a
measurement artifact, not a model capability result.

Why only the tool name changed

load_skill arguments carry the same SKILL.md path the existing predicate
already matches:

{"skill":"/skills/platform/evals/eval-experiment-authoring/SKILL.md"}

so only the tool-name check needed widening. No dataset annotations change.
filestore.read is retained for backwards compatibility with older traces.

Verification

Same-trace baseline on real golden-cluster data, holding the trace and skill
predicate fixed and varying only the tool name:

OLD (filestore.read only)   total_tool_spans=2  skill_invoked=0
NEW (load_skill accepted)   total_tool_spans=2  skill_invoked=1

The added regression test asserts the generated ES|QL includes load_skill.
It was confirmed to fail on the pre-fix predicate by reverting the one-line
change and re-running (1 failed, 13 skipped), then pass after restoring.

Local gates:

tsc     : exited with 0
eslint  : no eslint errors found
jest    : 14 passed, 14 total

Note for reviewers

This changes what the Skill Invoked column reports for all models. Existing
persona-matrix results showing SkillInvoked = 0 should be treated as
unreliable and regenerated rather than compared against post-fix runs.

Relationship to #283586

This fix is also cherry-picked onto #283586 (feat/evals-extensions-matrix), which
generates the security LLM performance matrix, so that PR's generated matrix does not
ship a Skill Invoked column built from the pre-fix predicate. This PR is the standalone
version, based directly on main, and can merge independently in either order.

@patrykkopycinski

Copy link
Copy Markdown
Contributor Author

buildkite test this

@patrykkopycinski

Copy link
Copy Markdown
Contributor Author

/ci

The persona-matrix SkillInvoked evaluator matched only
`attributes.gen_ai.tool.name == "filestore.read"`, but the agent loads
skills via the `load_skill` tool. Verified against the golden cluster
over a 7-day window:

    filestore.read  ->     0 spans
    load_skill      -> 7,991 spans

Because `total_tool_spans` is still non-zero for these traces, the
existing "no tool spans -> unavailable" guard does not trip. The
evaluator therefore returned a confident `score: 0` rather than `null`,
silently zeroing the Skill Invoked column for every model in every
persona-matrix run, not just for one model.

`load_skill` arguments carry the same SKILL.md path the existing
predicate already matches:

    {"skill":"/skills/platform/evals/eval-experiment-authoring/SKILL.md"}

so only the tool-name check needed widening; no dataset annotations
change. `filestore.read` is retained for backwards compatibility with
older traces.

Verified with a same-trace baseline on real golden-cluster data, holding
the trace and skill predicate fixed and varying only the tool name:

    OLD (filestore.read only)   total_tool_spans=2  skill_invoked=0
    NEW (load_skill accepted)   total_tool_spans=2  skill_invoked=1

The added regression test asserts the generated ES|QL includes
`load_skill`; it fails on the pre-fix predicate (confirmed by reverting
the one-line change and re-running: 1 failed, 13 skipped) and passes
after.
@patrykkopycinski
patrykkopycinski force-pushed the fix/persona-matrix-skill-invoked-load-skill branch from 4a4261b to 99d897e Compare August 12, 2026 14:22
@patrykkopycinski

Copy link
Copy Markdown
Contributor Author

/ci

@kibanamachine

Copy link
Copy Markdown
Contributor

💛 Build succeeded, but was flaky

Failed CI Steps

Metrics [docs]

✅ unchanged

Test Failures

  • [job] [logs] FTR Configs #86 / Entity Analytics - Entity Resolution @ess @serverless @skipInServerlessMKI Entity Resolution CSV Upload should link matching entities to a target

History

@patrykkopycinski
patrykkopycinski marked this pull request as ready for review August 12, 2026 15:52
@patrykkopycinski
patrykkopycinski requested a review from a team as a code owner August 12, 2026 15:52
@kibanamachine

Copy link
Copy Markdown
Contributor

🧪 LLM eval (PR) — Security Persona Matrix (security-persona-matrix) failed.

Failing models:

  • eis-zai-glm-5-2

View build

Triage summary:

_Triage summary could not be generated: Inference request failed (503):

<title>503 Service Unavailable</title>

Error: Service Unavailable

Service is disabled

. See the suite owner notify Buildkite step for details._

@patrykkopycinski patrykkopycinski added release_note:skip Skip the PR/issue when compiling release notes backport:skip This PR does not require backporting labels Aug 12, 2026
@patrykkopycinski
patrykkopycinski merged commit d2dc716 into elastic:main Aug 12, 2026
108 checks passed
qn895 pushed a commit to qn895/kibana that referenced this pull request Aug 13, 2026
…me (elastic#284661)

## Summary

The persona-matrix `SkillInvoked` evaluator matched only
`attributes.gen_ai.tool.name == "filestore.read"`, but the agent loads
skills
via the `load_skill` tool. Verified against the golden cluster over a
7-day
window:

| tool name | spans (7d) |
| --- | --- |
| `filestore.read` | 0 |
| `load_skill` | 7,991 |

Because `total_tool_spans` is still non-zero for these traces, the
existing
"no tool spans → `unavailable`" guard does not trip. The evaluator
therefore
returned a confident `score: 0` instead of `null` — silently zeroing the
**Skill Invoked** column for every model in every persona-matrix run,
not just
for one model.

This surfaced while generating a matrix column for a model that appeared
to
never route into any skill. Trace data showed the opposite: it invoked
`load_skill` and called security skills directly. The reported zero was
a
measurement artifact, not a model capability result.

## Why only the tool name changed

`load_skill` arguments carry the same `SKILL.md` path the existing
predicate
already matches:

```json
{"skill":"/skills/platform/evals/eval-experiment-authoring/SKILL.md"}
```

so only the tool-name check needed widening. No dataset annotations
change.
`filestore.read` is retained for backwards compatibility with older
traces.

## Verification

Same-trace baseline on real golden-cluster data, holding the trace and
skill
predicate fixed and varying only the tool name:

```
OLD (filestore.read only)   total_tool_spans=2  skill_invoked=0
NEW (load_skill accepted)   total_tool_spans=2  skill_invoked=1
```

The added regression test asserts the generated ES|QL includes
`load_skill`.
It was confirmed to fail on the pre-fix predicate by reverting the
one-line
change and re-running (`1 failed, 13 skipped`), then pass after
restoring.

Local gates:

```
tsc     : exited with 0
eslint  : no eslint errors found
jest    : 14 passed, 14 total
```

## Note for reviewers

This changes what the Skill Invoked column reports for **all** models.
Existing
persona-matrix results showing `SkillInvoked = 0` should be treated as
unreliable and regenerated rather than compared against post-fix runs.

## Relationship to elastic#283586

This fix is also cherry-picked onto elastic#283586
(`feat/evals-extensions-matrix`), which
generates the security LLM performance matrix, so that PR's generated
matrix does not
ship a Skill Invoked column built from the pre-fix predicate. This PR is
the standalone
version, based directly on `main`, and can merge independently in either
order.
patrykkopycinski added a commit to patrykkopycinski/kibana that referenced this pull request Aug 18, 2026
…me (elastic#284661)

## Summary

The persona-matrix `SkillInvoked` evaluator matched only
`attributes.gen_ai.tool.name == "filestore.read"`, but the agent loads
skills
via the `load_skill` tool. Verified against the golden cluster over a
7-day
window:

| tool name | spans (7d) |
| --- | --- |
| `filestore.read` | 0 |
| `load_skill` | 7,991 |

Because `total_tool_spans` is still non-zero for these traces, the
existing
"no tool spans → `unavailable`" guard does not trip. The evaluator
therefore
returned a confident `score: 0` instead of `null` — silently zeroing the
**Skill Invoked** column for every model in every persona-matrix run,
not just
for one model.

This surfaced while generating a matrix column for a model that appeared
to
never route into any skill. Trace data showed the opposite: it invoked
`load_skill` and called security skills directly. The reported zero was
a
measurement artifact, not a model capability result.

## Why only the tool name changed

`load_skill` arguments carry the same `SKILL.md` path the existing
predicate
already matches:

```json
{"skill":"/skills/platform/evals/eval-experiment-authoring/SKILL.md"}
```

so only the tool-name check needed widening. No dataset annotations
change.
`filestore.read` is retained for backwards compatibility with older
traces.

## Verification

Same-trace baseline on real golden-cluster data, holding the trace and
skill
predicate fixed and varying only the tool name:

```
OLD (filestore.read only)   total_tool_spans=2  skill_invoked=0
NEW (load_skill accepted)   total_tool_spans=2  skill_invoked=1
```

The added regression test asserts the generated ES|QL includes
`load_skill`.
It was confirmed to fail on the pre-fix predicate by reverting the
one-line
change and re-running (`1 failed, 13 skipped`), then pass after
restoring.

Local gates:

```
tsc     : exited with 0
eslint  : no eslint errors found
jest    : 14 passed, 14 total
```

## Note for reviewers

This changes what the Skill Invoked column reports for **all** models.
Existing
persona-matrix results showing `SkillInvoked = 0` should be treated as
unreliable and regenerated rather than compared against post-fix runs.

## Relationship to elastic#283586

This fix is also cherry-picked onto elastic#283586
(`feat/evals-extensions-matrix`), which
generates the security LLM performance matrix, so that PR's generated
matrix does not
ship a Skill Invoked column built from the pre-fix predicate. This PR is
the standalone
version, based directly on `main`, and can merge independently in either
order.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:skip This PR does not require backporting release_note:skip Skip the PR/issue when compiling release notes v9.6.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants