diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index 15839723ecef..f7c937a41103 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -333,8 +333,10 @@
* Fix Envoy ALS rendering for the LAL live-debugger and the persisted log `content`: an Istio metadata-exchange peer in `common_properties.filter_state_objects` (legacy Wasm `wasm.*_peer` = `Any{BytesValue}` wrapping a FlatBuffer, or modern `*_peer` = `Any{Struct}`) is now decoded into the readable peer metadata (pod / namespace / labels) instead of an opaque `jsonformat-failed` envelope or base64. The serialization is hardened so a single un-printable field can no longer blank the whole entry — the `LalPayloadDebugDump` printer carries a well-known-type `TypeRegistry` and sanitizes every value `JsonFormat` would reject (an unresolvable, no-slash, or corrupt-bytes `Any` degrades to an `@unresolved` placeholder; a non-finite `Value` double `NaN`/`Infinity` is rendered as a string), keeping the rest of the entry readable. Because the LAL output builder's `bindInput` runs eagerly before the debug capture, this also stops an unregistered `filter_state_objects` type from throwing and aborting the whole rule (dropping the mesh log). Decoding is wired through a new `LalInputDebugRenderer` SPI (`EnvoyAlsHttpDebugRenderer` / `EnvoyAlsTcpDebugRenderer`) so `log-analyzer` reaches the receiver-side decoders without depending on the Envoy receiver, and covers both HTTP and TCP access logs.
* Surface the effective BanyanDB configuration (`bydb.yml` / `bydb-topn.yml`) in the `/debugging/config/dump` admin API. Because the BanyanDB config moved to a separate file in 10.2.0, a BanyanDB deployment previously showed an empty `storage.banyandb` block in the dump; its post-environment-resolution values are now merged into the same response under `storage.banyandb.*` (TopN rules under `storage.banyandb.topN.*`), masked by the same secret-keyword list, via a generic `ConfigDumpExtension` SPI on `ServerStatusService` that any module loading config from a secondary file can implement.
* Fix: an MQE `top_n(metric, N, order, attrX='value')` query whose attribute is not a column of the target metric now returns a descriptive MQE error instead of a raw storage `IOException` surfaced as `Internal IO exception, query metrics error.`. Attribute columns (`attr0..attrN`) exist only on decorated metrics (`service_*` / `endpoint_*` / `kubernetes_service_*`, set to the layer name via OAL `.decorator(...)`) and the MAL meter base; metrics such as relations or database / cache / mq access carry none, so passing an attribute condition previously reached the storage engine with a tag it does not define and failed there. `MQEVisitor` now validates each attribute key against the metric's registered queryable columns before the storage call and raises `IllegalExpressionException` (naming the attribute and the metric) when it is absent.
+* Add customizable LLM-as-judge support for AI evaluation, with OpenAI-compatible endpoint / model / API key configuration, and persist the evaluation result as queryable `GenAIEvaluationRecord` rows for later inspection.
#### UI
+* Add a Virtual GenAI evaluation-record page and evaluation-score chart in Horizon UI, so operators can inspect evaluation result, level, reason, judge model, timestamp, trace linkage, and the `gen_ai_model_evaluation_score_ppm` trend for evaluated records.
* Add Airflow layer dashboards and menu i18n under Workflow Scheduler in Horizon UI (SWIP-7).
* Add mobile menu icon and i18n labels for the iOS layer.
* Fix metric label rendering in multi-expression dashboard widgets.
diff --git a/docs/en/swip/SWIP-16.md b/docs/en/swip/SWIP-16.md
new file mode 100644
index 000000000000..8450ffc069c4
--- /dev/null
+++ b/docs/en/swip/SWIP-16.md
@@ -0,0 +1,260 @@
+# SWIP-16 Support LLM-as-Judge on Top of GenAI Observability
+
+## Motivation
+
+SkyWalking already provides GenAI observability capabilities. Based on the existing GenAI semantic conventions and analysis pipeline, SkyWalking can recognize GenAI spans from multiple data sources, including SkyWalking native traces, OTLP, and Zipkin, extract GenAI-related attributes, build Virtual GenAI entities, and display runtime metrics such as traffic, latency, token usage, TTFT, TPOT, and estimated cost in the GenAI dashboard.
+
+These capabilities answer "what happened during the invocation" and "how are performance and cost," but they do not yet answer "what is the quality of the model output." For GenAI applications in production, users usually also need to continuously observe quality signals such as:
+
+- Whether the response is faithful to the given context
+- Whether the response is relevant to the user query
+- Whether the model completes the expected task
+- Whether the response contains hallucinations
+
+Today, such evaluation usually depends on external evaluation platforms, custom business-side scripts, or manual sampling workflows. This causes several problems:
+
+- Evaluation results are disconnected from SkyWalking trace and span observability data
+- Evaluation results cannot be stored as unified structured data in SkyWalking
+- Evaluation tasks lack a unified OAP-side configuration model
+- Evaluation results cannot be further aggregated into metrics and displayed in the existing GenAI dashboard
+
+This SWIP proposes introducing `LLM-as-Judge` into SkyWalking OAP. On top of the existing GenAI observability capabilities, the whole evaluation feature reuses the current trace ingestion and GenAI span analysis pipeline and supports SkyWalking native traces, OTLP, and Zipkin as input sources. OAP samples runtime GenAI spans, extracts evaluation inputs, invokes a configurable judge model, and writes evaluation results into SkyWalking structured records. For `SCORE`-type evaluation results, OAP further generates metrics and displays them in the GenAI dashboard. Meanwhile, the UI adds an evaluation result page for detailed result browsing and supports jumping from a single evaluation result to the related trace, so that quality observability is integrated into the existing GenAI observability system.
+
+## Architecture Graph
+
+```text
+GenAI spans / traces SkyWalking OAP Storage / Query / UI
+------------------- -------------- --------------------
+SkyWalking native / OTLP / Zipkin -> GenAI span analysis
+ |- recognize GenAI spans
+ |- extract context and tags
+ '- trigger AI evaluation
+ |
+ v
+ ai-evaluation module
+ |- PPM sampling strategy
+ |- evaluation planning
+ |- prompt building
+ |- Judge Provider
+ '- result parsing
+ |
+ v
+ External Judge Model
+ |
+ v
+ Evaluation result
+ |- write structured record
+ '- generate MAL labeled metrics for SCORE results
+ |
+ +---------------------+----------------------+
+ | |
+ v v
+ records storage (`ai_evaluation_result`) GraphQL / query API / GenAI dashboard / evaluation result view
+```
+
+## Proposed Changes
+
+### 1. Introduce an independent AI evaluation module
+
+OAP adds a dedicated `ai-evaluation` module to host runtime AI evaluation capabilities. In the current implementation, evaluation data is decoupled through an asynchronous local in-memory queue so that judge invocation is not executed synchronously on the trace analysis critical path. This module is responsible for:
+
+- Loading evaluation-related configuration
+- Validating judge model configuration
+- Creating the judge provider
+- Applying the sampling strategy
+- Executing the evaluation strategy
+- Persisting evaluation results
+- Converting score-type evaluation results into MAL-based labeled metrics
+
+This keeps evaluation logic modular and avoids coupling judge-related logic directly into the existing analyzer core.
+
+### 2. Reuse the existing GenAI observability analysis entry
+
+This capability does not introduce a new parallel collection pipeline. Instead, it is built on top of the existing GenAI observability capability and directly reuses the current trace ingestion paths, including SkyWalking native traces, OTLP, and Zipkin.
+
+When OAP parses spans, the existing pipeline already recognizes GenAI spans. On top of that, the new analysis listener reuses runtime context and extracts the following information:
+
+- `traceId`
+- `spanId`
+- `serviceName`
+- `serviceInstanceName`
+- `operationName`
+- `providerName`
+- `modelName`
+- `startTimeMillis`
+- `endTimeMillis`
+- `error`
+- `GenAI-related tags`
+
+This information is packaged as the evaluation context and passed to the AI evaluation service, making evaluation results a natural extension of the existing GenAI observability model.
+
+### 3. Introduce task-based LLM-as-Judge evaluation
+
+The evaluation logic is task-driven rather than hardcoded around fixed dimensions. Each task defines the following fields:
+
+- `name`
+- `valueType`
+- `instruction`
+
+The initial default tasks include:
+
+- `Faithfulness`
+- `Relevance`
+- `TaskCompletion`
+- `Hallucination`
+
+Based on the configured `system-prompt`, extracted GenAI context, and task list, OAP builds the prompt and sends it to the external judge model. The judge model returns structured JSON, and each task result contains at least:
+
+- `value`
+- `reason`
+
+This design keeps evaluation dimensions configurable rather than hardcoded in the implementation.
+
+### 4. Support an OpenAI-compatible judge provider
+
+This SWIP introduces the `JudgeModelProvider` abstraction and provides the first implementation, `OpenAICompatibleProvider`.
+
+Runtime configuration includes:
+
+- `provider`
+- `endpoint`
+- `model`
+- `api-key`
+
+This allows OAP to call judge endpoints compatible with the OpenAI API format while leaving room for future provider extensions.
+
+### 5. Introduce evaluation planning, prompt building, asynchronous queueing, and result parsing
+
+The implementation introduces a clear runtime evaluation pipeline. In the current implementation, after a GenAI span hits sampling, OAP does not synchronously invoke evaluation. Instead, it first places the evaluation task into a local asynchronous in-memory queue, and a background evaluation consumer executes the remaining steps:
+
+- `EvaluationInputExtractor`
+- `EvaluationPlanner`
+- `EvaluationPlan`
+- `EvaluationPromptBuilder`
+- `local async in-memory queue`
+- `evaluation consumer`
+- `EvaluationResultParser`
+- `EvaluationResult`
+
+The end-to-end flow is:
+
+1. Extract evaluation input from the GenAI span context
+2. Build the evaluation plan according to configured tasks
+3. Put the evaluation task into the asynchronous local in-memory queue
+4. The background evaluation consumer takes the task from the queue and builds the judge prompt
+5. Invoke the judge model
+6. Parse the returned JSON into structured evaluation results
+7. Persist the evaluation results and generate MAL labeled metrics when applicable
+
+This decouples evaluation orchestration from transport and storage logic and avoids blocking external model invocation on the trace analysis critical path.
+
+### 6. Use PPM sampling for runtime evaluation
+
+Because LLM-as-Judge introduces additional model invocation cost and runtime overhead, this SWIP does not evaluate all GenAI spans. Instead, it introduces a sampling strategy.
+
+The sampling rate uses PPM, `parts per million`:
+
+- `1_000_000` means 100% evaluation
+- `100_000` means 10% evaluation
+- `10_000` means 1% evaluation
+- `0` means runtime evaluation is disabled
+
+The module validates that the sampling rate is within `[0, 1_000_000]` and applies the configured sampling strategy before invoking the judge model.
+
+### 7. Write evaluation results into SkyWalking structured records
+
+Each evaluation result is written into SkyWalking storage through `AIEvaluationResultRecord` as a structured record.
+
+The record includes the following core fields:
+
+- `trace_id`
+- `segment_id`
+- `span_id`
+- `span_type`
+- `task_name`
+- `value_type`
+- `value`
+- `evaluation_level`
+- `reason`
+- `judge_model`
+- `evaluation_time`
+- `time_bucket`
+
+This lets each evaluation result directly link back to existing trace and span data. OAP also derives a normalized `evaluation_level` from the returned result when the value type supports level resolution, so later query and UI layers can filter and group records by coarse quality level in addition to raw value. In merged record storage mode, the data is written into the logical record table `ai_evaluation_result`.
+
+### 8. Generate MAL labeled metrics from SCORE-type evaluation results
+
+In addition to persisting evaluation results as structured records, this SWIP also proposes converting `SCORE`-type evaluation results into MAL-based labeled metrics.
+
+For tasks where `valueType = SCORE`, the judge returns a numeric result in `[0.0, 1.0]`. OAP converts the result into a MAL `SampleFamily` and uses a MAL rule to generate the final metric. The task name is kept as a metric label instead of being encoded into the metric name, so newly configured evaluation tasks do not require additional OAL statements or new hardcoded metrics.
+
+The initial metric is:
+
+- `gen_ai_evaluation_score_ppm`
+
+The metric is attached to the Virtual GenAI service instance dimension, using `service_name` as the service key and `model_name` as the instance key. The `task_name` remains as a labeled value dimension, allowing the same metric to represent scores for `Faithfulness`, `Relevance`, `TaskCompletion`, `Hallucination`, or any user-defined task.
+
+Because SkyWalking MAL labeled values are stored as long values, the score is scaled before entering the MAL pipeline:
+
+```text
+stored value = score * 1,000,000
+```
+
+For example, a judge score of `0.86` is stored as `860000`. Query or UI code should divide the metric value by `1,000,000` when displaying the original score.
+
+This labeled metric supports:
+
+- Observing score trends by evaluation task
+- Aggregating evaluation results by existing GenAI observability dimensions, especially service and model
+- Displaying quality-related metrics grouped by `task_name` in the GenAI dashboard
+
+This means the new capability is not only a record persistence feature, but also extends the GenAI dashboard from performance and cost observability to quality observability.
+
+### 9. Add an evaluation result page and trace jump capability
+
+In addition to aggregated dashboard metrics, the UI adds an evaluation result page for displaying structured evaluation details.
+
+The page displays at least the following fields:
+
+- `traceId`
+- `segmentId`
+- `spanId`
+- `serviceName`
+- `operationName`
+- `taskName`
+- `valueType`
+- `value`
+- `evaluationLevel`
+- `reason`
+- `judgeModel`
+- `evaluationTime`
+
+Users can filter the page by service, task name, evaluation level, time range, and other tag-based conditions, making it easier to investigate low scores, anomalies, or suspicious results.
+
+Most importantly, each evaluation result keeps its association with the original trace. Users can click `traceId` or a jump button in the evaluation result page to open the related trace detail page directly and continue investigating the full call chain, contextual spans, and related GenAI tags.
+
+This allows SkyWalking not only to show an evaluation result, but also to connect that result with runtime trace analysis and form a closed-loop troubleshooting experience from quality signal to execution context.
+
+## Compatibility
+
+This SWIP introduces a new OAP capability and a new record data model. The main compatibility impacts include:
+
+- A new structured record type `ai_evaluation_result`, including the normalized `evaluation_level` field
+- `SCORE`-type evaluation results additionally generate a MAL labeled metric for dashboard display
+- The `gen_ai_evaluation_score_ppm` metric stores scores scaled by `1,000,000`; query and UI layers need to divide by `1,000,000` to display the original `[0.0, 1.0]` score
+- The capability depends on the existing GenAI observability pipeline being able to recognize GenAI spans from SkyWalking native traces, OTLP, and Zipkin
+- The UI adds an evaluation result page and trace jump based on `traceId`
+- The current implementation uses an asynchronous local in-memory queue to carry evaluation tasks, and queue data is not part of any persistent protocol
+- Runtime behavior is controlled jointly by the module switch, judge configuration, task configuration, and PPM sampling rate
+
+## General usage docs
+
+1. Enable the `ai-evaluation` module in OAP.
+2. Configure the judge provider, endpoint, model, API key, system prompt, task list, and PPM sampling rate.
+3. Ensure the existing GenAI observability pipeline is already receiving supported GenAI spans from SkyWalking native traces, OTLP, and Zipkin.
+4. OAP generates evaluation tasks for sampled GenAI spans according to the PPM sampling rate and puts them into the asynchronous local in-memory queue.
+5. A background evaluation consumer takes tasks from the queue and sends requests to the configured judge model.
+6. OAP writes each evaluation result into SkyWalking structured records.
+7. For `SCORE`-type tasks, OAP generates the MAL labeled metric `gen_ai_evaluation_score_ppm` from evaluation results.
+8. Users observe both existing GenAI runtime metrics and newly added quality metrics in the GenAI dashboard. The UI should divide `gen_ai_evaluation_score_ppm` values by `1,000,000` to display the original score.
+9. Users can also open the evaluation result page, inspect evaluation details, and jump from a single result to the related trace.
\ No newline at end of file
diff --git a/docs/en/swip/readme.md b/docs/en/swip/readme.md
index eac834e4a184..a9ca425de24d 100644
--- a/docs/en/swip/readme.md
+++ b/docs/en/swip/readme.md
@@ -68,7 +68,7 @@ All accepted and proposed SWIPs can be found in [here](https://github.com/apache
## Known SWIPs
-Next SWIP Number: 16
+Next SWIP Number: 17
### Proposed SWIPs
@@ -78,6 +78,7 @@ Next SWIP Number: 16
### Accepted SWIPs
+- [SWIP-16 Support LLM-as-Judge on Top of GenAI Observability](SWIP-16.md)
- [SWIP-12 Support WeChat & Alipay Mini Program Monitoring](SWIP-12.md)
- [SWIP-11 Support iOS App Monitoring via OpenTelemetry](SWIP-11.md)
- [SWIP-10 Support Envoy AI Gateway Observability](SWIP-10/SWIP.md)
diff --git a/oap-server/ai-evaluation/pom.xml b/oap-server/ai-evaluation/pom.xml
new file mode 100644
index 000000000000..43887e3a8261
--- /dev/null
+++ b/oap-server/ai-evaluation/pom.xml
@@ -0,0 +1,58 @@
+
+
+
+
+ 4.0.0
+
+
+ org.apache.skywalking
+ oap-server
+ ${revision}
+
+
+ org.apache.skywalking
+ ai-evaluation
+
+
+ AI evaluation module samples telemetry data from the OAP kernel, builds evaluation tasks for AI scenarios,
+ and calls a judge model to evaluate the observed AI behavior.
+
+
+
+
+ org.apache.skywalking
+ library-module
+ ${project.version}
+
+
+ org.apache.skywalking
+ server-core
+ ${project.version}
+
+
+ org.apache.skywalking
+ meter-analyzer
+ ${project.version}
+
+
+ com.google.code.gson
+ gson
+
+
+
diff --git a/oap-server/ai-evaluation/src/main/java/org/apache/skywalking/oap/server/ai/evaluation/AIEvaluationConfig.java b/oap-server/ai-evaluation/src/main/java/org/apache/skywalking/oap/server/ai/evaluation/AIEvaluationConfig.java
new file mode 100644
index 000000000000..319fcd392dd0
--- /dev/null
+++ b/oap-server/ai-evaluation/src/main/java/org/apache/skywalking/oap/server/ai/evaluation/AIEvaluationConfig.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.ai.evaluation;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.skywalking.oap.server.ai.evaluation.level.EvaluationLevelConfig;
+import org.apache.skywalking.oap.server.ai.evaluation.task.EvaluationTask;
+import org.apache.skywalking.oap.server.library.module.ModuleConfig;
+
+@Getter
+@Setter
+public class AIEvaluationConfig extends ModuleConfig {
+ private int sampleRate;
+ private Properties judge = new Properties();
+ private String systemPrompt;
+ private Double temperature;
+ private Integer maxTokens;
+ private List tasks = new ArrayList<>();
+ private EvaluationLevelConfig level = new EvaluationLevelConfig();
+}
diff --git a/oap-server/ai-evaluation/src/main/java/org/apache/skywalking/oap/server/ai/evaluation/AIEvaluationConfigLoader.java b/oap-server/ai-evaluation/src/main/java/org/apache/skywalking/oap/server/ai/evaluation/AIEvaluationConfigLoader.java
new file mode 100644
index 000000000000..f31f814f9849
--- /dev/null
+++ b/oap-server/ai-evaluation/src/main/java/org/apache/skywalking/oap/server/ai/evaluation/AIEvaluationConfigLoader.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.ai.evaluation;
+
+import java.io.FileNotFoundException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.function.Consumer;
+import org.apache.skywalking.oap.server.ai.evaluation.level.EvaluationLevelConfig;
+import org.apache.skywalking.oap.server.ai.evaluation.level.ScoreLevelRule;
+import org.apache.skywalking.oap.server.ai.evaluation.task.EvaluationTask;
+import org.apache.skywalking.oap.server.ai.evaluation.value.ValueType;
+import org.apache.skywalking.oap.server.library.module.ModuleStartException;
+import org.apache.skywalking.oap.server.library.util.ResourceUtils;
+import org.apache.skywalking.oap.server.library.util.YamlConfigLoaderUtils;
+import org.yaml.snakeyaml.Yaml;
+
+public class AIEvaluationConfigLoader {
+ private static final String CONFIG_FILE = "ai-evaluation.yml";
+
+ public AIEvaluationConfig load() throws ModuleStartException {
+ try {
+ final Reader reader = ResourceUtils.read(CONFIG_FILE);
+ final Map loaded = new Yaml().loadAs(reader, Map.class);
+ if (loaded == null || loaded.isEmpty()) {
+ return new AIEvaluationConfig();
+ }
+ return buildConfig(loaded);
+ } catch (FileNotFoundException e) {
+ throw new ModuleStartException("Cannot find the AI evaluation configuration file ["
+ + CONFIG_FILE + "].", e);
+ }
+ }
+
+ private AIEvaluationConfig buildConfig(final Map loaded) {
+ final AIEvaluationConfig config = new AIEvaluationConfig();
+
+ final Object judge = loaded.get("judge");
+ if (judge instanceof Map) {
+ config.setJudge(buildProperties((Map) judge));
+ }
+
+ final Object systemPrompt = loaded.get("system-prompt");
+ if (systemPrompt != null) {
+ config.setSystemPrompt(String.valueOf(systemPrompt));
+ }
+
+ final Object level = loaded.get("level");
+ if (level instanceof Map) {
+ config.setLevel(buildLevelConfig((Map) level));
+ }
+
+ final Object tasks = loaded.get("tasks");
+ if (tasks instanceof List) {
+ for (Map taskConfig : (List