Skip to content

Commit da914a2

Browse files
Merge pull request #98 from ajimenez1503/feat/grpc-receiver-support
gRPC OTel Receiver support
2 parents 86255f6 + 606d42c commit da914a2

19 files changed

Lines changed: 970 additions & 492 deletions

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ USER app
3333
ENV PATH="/app/.venv/bin:$PATH"
3434
ENV AGENTEVALS_SERVER_URL=http://127.0.0.1:8001
3535

36-
EXPOSE 8001 4318 8080
36+
EXPOSE 8001 4318 4317 8080
3737

38-
CMD ["agentevals", "serve", "--host", "0.0.0.0", "--port", "8001", "--otlp-port", "4318", "--mcp-port", "8080"]
38+
CMD ["agentevals", "serve", "--host", "0.0.0.0", "--port", "8001", "--otlp-http-port", "4318", "--otlp-grpc-port", "4317", "--mcp-port", "8080"]

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,14 @@ export OTEL_RESOURCE_ATTRIBUTES="agentevals.session_name=my-agent"
140140
python your_agent.py
141141
```
142142

143-
Traces stream to the UI in real-time. Works with LangChain, Strands, Google ADK, OpenAI Agents SDK, or any framework that emits OTel spans (`http/protobuf` and `http/json` supported). Sessions are auto-created and grouped by `agentevals.session_name`. Set `agentevals.eval_set_id` to associate traces with an eval set.
143+
For OTLP/gRPC exporters, use:
144+
145+
```bash
146+
export OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317
147+
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
148+
```
149+
150+
Traces stream to the UI in real-time. Works with LangChain, Strands, Google ADK, OpenAI Agents SDK, or any framework that emits OTel spans (`http/protobuf`, `http/json`, and OTLP/gRPC supported). Sessions are auto-created and grouped by `agentevals.session_name`. Set `agentevals.eval_set_id` to associate traces with an eval set.
144151

145152
See [examples/zero-code-examples/](examples/zero-code-examples/) for working examples.
146153

charts/agentevals/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
apiVersion: v2
22
name: agentevals
3-
description: agentevals web UI, OTLP HTTP receiver, and MCP (Streamable HTTP)
3+
description: agentevals web UI, OTLP HTTP+gRPC receivers, and MCP (Streamable HTTP)
44
type: application
55
version: 0.1.0
66
appVersion: "0.5.2"

charts/agentevals/templates/NOTES.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
1. UI and API are available at port {{ .Values.service.http.port }} (Service port name: http).
22
2. OTLP HTTP receiver: port {{ .Values.service.otlpHttp.port }} (OTEL_EXPORTER_OTLP_ENDPOINT=http://<service>:{{ .Values.service.otlpHttp.port }}).
3-
3. MCP (Streamable HTTP): port {{ .Values.service.mcp.port }}, path /mcp (e.g. http://<service>:{{ .Values.service.mcp.port }}/mcp).
3+
3. OTLP gRPC receiver: port {{ .Values.service.otlpGrpc.port }} (OTEL_EXPORTER_OTLP_ENDPOINT=<service>:{{ .Values.service.otlpGrpc.port }}, OTEL_EXPORTER_OTLP_PROTOCOL=grpc).
4+
4. MCP (Streamable HTTP): port {{ .Values.service.mcp.port }}, path /mcp (e.g. http://<service>:{{ .Values.service.mcp.port }}/mcp).
45
{{- if .Values.ephemeralVolume.enabled }}
5-
4. An emptyDir is mounted at /tmp with HOME=/tmp/agentevals-home (ephemeral; lost on pod restart). Set ephemeralVolume.enabled=false and readOnlyRootFilesystem=false if you need a writable root without this mount.
6+
5. An emptyDir is mounted at /tmp with HOME=/tmp/agentevals-home (ephemeral; lost on pod restart). Set ephemeralVolume.enabled=false and readOnlyRootFilesystem=false if you need a writable root without this mount.
67
{{- end }}
78

89
Get the Service URL:

charts/agentevals/templates/deployment.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ spec:
7979
- name: otlp-http
8080
containerPort: {{ .Values.service.otlpHttp.containerPort }}
8181
protocol: TCP
82+
- name: otlp-grpc
83+
containerPort: {{ .Values.service.otlpGrpc.containerPort }}
84+
protocol: TCP
8285
- name: mcp
8386
containerPort: {{ .Values.service.mcp.containerPort }}
8487
protocol: TCP

charts/agentevals/templates/service.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ spec:
1616
port: {{ .Values.service.otlpHttp.port }}
1717
targetPort: otlp-http
1818
protocol: TCP
19+
- name: otlp-grpc
20+
port: {{ .Values.service.otlpGrpc.port }}
21+
targetPort: otlp-grpc
22+
protocol: TCP
1923
- name: mcp
2024
port: {{ .Values.service.mcp.port }}
2125
targetPort: mcp

charts/agentevals/values.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ service:
111111
otlpHttp:
112112
port: 4318
113113
containerPort: 4318
114+
# -- OTLP gRPC receiver port
115+
otlpGrpc:
116+
port: 4317
117+
containerPort: 4317
114118
# -- MCP (Streamable HTTP) port
115119
mcp:
116120
port: 8080

docs/otel-compatibility.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,18 @@ If you maintain an OTel-instrumented agent framework and want to align with the
8080

8181
## OTLP Receiver
8282

83-
agentevals runs an OTLP HTTP receiver on port 4318 (the standard OTLP HTTP port) that accepts:
83+
agentevals runs:
84+
85+
- OTLP HTTP receiver on port 4318 (standard OTLP HTTP port)
86+
- OTLP gRPC receiver on port 4317 (standard OTLP gRPC port).
87+
88+
OTLP HTTP accepts:
8489

8590
| Endpoint | Content Types |
8691
|----------|--------------|
8792
| `/v1/traces` | `application/json`, `application/x-protobuf` |
8893
| `/v1/logs` | `application/json`, `application/x-protobuf` |
8994

90-
Point your standard OTel exporters at `http://localhost:4318` and traces will stream into agentevals automatically. See [examples/README.md](../examples/README.md) for zero-code setup instructions.
95+
Point OTLP/HTTP exporters at `http://localhost:4318`.
96+
Point OTLP/gRPC exporters at `localhost:4317` with `OTEL_EXPORTER_OTLP_PROTOCOL=grpc`.
97+
Traces and logs stream into agentevals automatically. See [examples/README.md](../examples/README.md) for zero-code setup instructions.

examples/README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,14 @@ export OTEL_RESOURCE_ATTRIBUTES="agentevals.session_name=my-agent,agentevals.eva
1414
python your_agent.py
1515
```
1616

17-
The OTLP receiver runs on port 4318 (standard OTLP HTTP port) and accepts both `http/protobuf` and `http/json`. Sessions are auto-created from incoming traces and grouped by `agentevals.session_name`.
17+
For OTLP/gRPC exporters, use:
18+
19+
```bash
20+
export OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317
21+
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
22+
```
23+
24+
agentevals accepts OTLP/HTTP on port 4318 (`http/protobuf` and `http/json`) and OTLP/gRPC on port 4317. Sessions are auto-created from incoming traces and grouped by `agentevals.session_name`.
1825

1926
| Example | Framework | LLM Provider |
2027
|---------|-----------|-------------|
@@ -108,7 +115,7 @@ The zero-code and SDK examples implement the same toy agent (dice rolling + prim
108115

109116
| Example | Description |
110117
|---------|-------------|
111-
| [kubernetes/](./kubernetes/) | Deploy agentevals with kagent on Kubernetes, using an OTel Collector as a gRPC to HTTP bridge. Includes a walkthrough for comparing two kagent agents (different models) and evaluating them with tool trajectory and response match scores. |
118+
| [kubernetes/](./kubernetes/) | Deploy agentevals with kagent on Kubernetes using native OTLP gRPC ingestion (or optionally an OTel Collector). Includes a walkthrough for comparing two kagent agents (different models) and evaluating them with tool trajectory and response match scores. |
112119

113120
## Advanced: GenAI Semantic Convention Patterns
114121

examples/kubernetes/README.md

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
Run agentevals alongside [kagent](https://github.com/kagent-dev/kagent) on Kubernetes to evaluate AI agent conversations in real time. This example deploys three components:
44

55
1. **agentevals** receives OTLP traces over HTTP and serves the evaluation UI
6-
2. **OTel Collector** bridges the protocol gap: kagent exports traces via gRPC, but agentevals only supports OTLP/HTTP today, so the Collector converts gRPC to HTTP
6+
2. **OTel Collector** Optional, useful when you want centralized telemetry
7+
controls.
78
3. **kagent** provides Kubernetes-native AI agents with built-in OTel instrumentation (gRPC export only)
89

910
```
10-
kagent (gRPC :4317) --> OTel Collector --> agentevals (HTTP :4318)
11-
|
12-
UI on :8001
11+
kagent (gRPC :4317) --> OTel Collector( optional ) --> agentevals (gRPC :4317 / HTTP :4318)
12+
|
13+
UI on :8001
1314
```
1415

1516
## Prerequisites
@@ -33,12 +34,20 @@ This creates a single pod exposing:
3334
| Port | Purpose |
3435
|------|---------|
3536
| 8001 | Web UI and API |
37+
| 4317 | OTLP gRPC receiver (traces and logs) |
3638
| 4318 | OTLP HTTP receiver (traces and logs) |
3739
| 8080 | MCP (Streamable HTTP) |
3840

39-
### 2. OTel Collector (gRPC to HTTP bridge)
41+
### 2. OTel Collector (optional)
4042

41-
kagent exports traces over gRPC (port 4317), but agentevals accepts OTLP over HTTP (port 4318). The OTel Collector bridges the two protocols.
43+
Native gRPC ingestion in agentevals is sufficient for most setups, but an
44+
intermediate collector is still useful when you want centralized telemetry
45+
controls:
46+
47+
- traffic shaping (batching, retries, backpressure)
48+
- filtering or redaction before data reaches agentevals
49+
- routing/fan-out to additional backends
50+
- protocol translation for mixed clients
4251

4352
```bash
4453
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
@@ -51,15 +60,15 @@ helm upgrade --install otel-collector open-telemetry/opentelemetry-collector \
5160
--set image.repository=otel/opentelemetry-collector \
5261
--set ports.otlp.enabled=true \
5362
--set ports.otlp-http.enabled=false \
54-
--set config.exporters.otlphttp.endpoint="http://agentevals.default.svc.cluster.local:4318" \
55-
--set config.exporters.otlphttp.compression="none" \
63+
--set config.exporters.otlp.endpoint="agentevals.default.svc.cluster.local:4317" \
64+
--set config.exporters.otlp.compression="gzip" \
5665
--set config.service.pipelines.traces.receivers[0]=otlp \
57-
--set config.service.pipelines.traces.exporters[0]=otlphttp \
66+
--set config.service.pipelines.traces.exporters[0]=otlp \
5867
--set config.service.pipelines.logs.receivers[0]=otlp \
59-
--set config.service.pipelines.logs.exporters[0]=otlphttp
68+
--set config.service.pipelines.logs.exporters[0]=otlp
6069
```
6170

62-
> **Note:** If you deployed agentevals in a namespace other than `default`, update the `endpoint` value accordingly: `http://agentevals.<namespace>.svc.cluster.local:4318`.
71+
> **Note:** If you deployed agentevals in a namespace other than `default`, update the `endpoint` value accordingly: `http://agentevals.<namespace>.svc.cluster.local:4317`.
6372
6473
### 3. kagent
6574

@@ -89,6 +98,8 @@ helm upgrade --install kagent oci://ghcr.io/kagent-dev/kagent/helm/kagent \
8998

9099
This installs kagent with only the default Helm agent (`helm-agent`) and the K8s troubleshooter enabled, and points its OTel exporter at the Collector.
91100

101+
> **Note:** If you are not running an OTel Collector, point `otel.tracing.exporter.otlp.endpoint` directly to the agentevals OTLP gRPC endpoint instead: `agentevals.default.svc.cluster.local:4317`.
102+
92103
### Verify the deployment
93104

94105
```bash

0 commit comments

Comments
 (0)