Skip to content

feat: emit canonical conversation telemetry from agent server - #4459

Merged
malhotra5 merged 2 commits into
mainfrom
oss-8687-canonical-conversation-telemetry
Aug 11, 2026
Merged

feat: emit canonical conversation telemetry from agent server#4459
malhotra5 merged 2 commits into
mainfrom
oss-8687-canonical-conversation-telemetry

Conversation

@malhotra5

@malhotra5 malhotra5 commented Aug 11, 2026

Copy link
Copy Markdown
Member

HUMAN:
Canonicalize conversation creation telemetry around the agent-server source of truth.

AGENT:

Why

  • The conversation KPI should count only real agent-server conversations, not browser or request-level milestones.
  • PostHog retries need a deterministic $insert_id to avoid duplicate KPI counts.

How to Test

  • uv run pytest tests/agent_server/telemetry/test_telemetry_subscriber.py tests/agent_server/telemetry/test_telemetry_end_to_end.py tests/agent_server/telemetry/test_telemetry_schema.py -q
  • uv run pytest tests/agent_server/telemetry/test_telemetry_exporter_posthog.py -q

Summary

  • Emits canonical agent_server.conversation_created telemetry from agent-server for genuinely new conversations.
  • Adds deterministic $insert_id values based on the sanitized conversation reference.
  • Updates telemetry tests/docs from the old started milestone to the canonical created milestone.

This PR description was updated by an AI agent (OpenHands) on behalf of the user.


🐳 Agent Server images for this PR — GHCR package, pull/run commands, and all pushed tags (click to expand)

GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Architectures Base Image Docs / Tags
java amd64, arm64 eclipse-temurin:17-jdk Link
python amd64, arm64 nikolaik/python-nodejs:python3.13-nodejs22-slim Link
golang amd64, arm64 golang:1.21-bookworm Link

Pull (multi-arch manifest)

# Each variant is a multi-arch manifest supporting both amd64 and arm64
docker pull ghcr.io/openhands/agent-server:c96c16a-python

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-c96c16a-python \
  ghcr.io/openhands/agent-server:c96c16a-python

All tags pushed for this build

ghcr.io/openhands/agent-server:c96c16a-golang-amd64
ghcr.io/openhands/agent-server:c96c16a9ac1969effd40aff80d7f7db5222ebbd5-golang-amd64
ghcr.io/openhands/agent-server:oss-8687-canonical-conversation-telemetry-golang-amd64
ghcr.io/openhands/agent-server:c96c16a-golang_tag_1.21-bookworm-amd64
ghcr.io/openhands/agent-server:c96c16a-golang-arm64
ghcr.io/openhands/agent-server:c96c16a9ac1969effd40aff80d7f7db5222ebbd5-golang-arm64
ghcr.io/openhands/agent-server:oss-8687-canonical-conversation-telemetry-golang-arm64
ghcr.io/openhands/agent-server:c96c16a-golang_tag_1.21-bookworm-arm64
ghcr.io/openhands/agent-server:c96c16a-java-amd64
ghcr.io/openhands/agent-server:c96c16a9ac1969effd40aff80d7f7db5222ebbd5-java-amd64
ghcr.io/openhands/agent-server:oss-8687-canonical-conversation-telemetry-java-amd64
ghcr.io/openhands/agent-server:c96c16a-eclipse-temurin_tag_17-jdk-amd64
ghcr.io/openhands/agent-server:c96c16a-java-arm64
ghcr.io/openhands/agent-server:c96c16a9ac1969effd40aff80d7f7db5222ebbd5-java-arm64
ghcr.io/openhands/agent-server:oss-8687-canonical-conversation-telemetry-java-arm64
ghcr.io/openhands/agent-server:c96c16a-eclipse-temurin_tag_17-jdk-arm64
ghcr.io/openhands/agent-server:c96c16a-python-amd64
ghcr.io/openhands/agent-server:c96c16a9ac1969effd40aff80d7f7db5222ebbd5-python-amd64
ghcr.io/openhands/agent-server:oss-8687-canonical-conversation-telemetry-python-amd64
ghcr.io/openhands/agent-server:c96c16a-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-amd64
ghcr.io/openhands/agent-server:c96c16a-python-arm64
ghcr.io/openhands/agent-server:c96c16a9ac1969effd40aff80d7f7db5222ebbd5-python-arm64
ghcr.io/openhands/agent-server:oss-8687-canonical-conversation-telemetry-python-arm64
ghcr.io/openhands/agent-server:c96c16a-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-arm64
ghcr.io/openhands/agent-server:c96c16a-golang
ghcr.io/openhands/agent-server:c96c16a9ac1969effd40aff80d7f7db5222ebbd5-golang
ghcr.io/openhands/agent-server:oss-8687-canonical-conversation-telemetry-golang
ghcr.io/openhands/agent-server:c96c16a-golang_tag_1.21-bookworm
ghcr.io/openhands/agent-server:c96c16a-java
ghcr.io/openhands/agent-server:c96c16a9ac1969effd40aff80d7f7db5222ebbd5-java
ghcr.io/openhands/agent-server:oss-8687-canonical-conversation-telemetry-java
ghcr.io/openhands/agent-server:c96c16a-eclipse-temurin_tag_17-jdk
ghcr.io/openhands/agent-server:c96c16a-python
ghcr.io/openhands/agent-server:c96c16a9ac1969effd40aff80d7f7db5222ebbd5-python
ghcr.io/openhands/agent-server:oss-8687-canonical-conversation-telemetry-python
ghcr.io/openhands/agent-server:c96c16a-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim

About Multi-Architecture Support

  • Each variant tag (e.g., c96c16a-python) is a multi-arch manifest supporting both amd64 and arm64
  • Docker automatically pulls the correct architecture for your platform
  • Individual architecture tags (e.g., c96c16a-python-amd64) are also available if needed

@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Python API breakage checks — ✅ PASSED

Result:PASSED

Action log

@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

REST API breakage checks (OpenAPI) — ✅ PASSED

Result:PASSED

Action log

@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Coverage

Coverage Report •
FileStmtsMissCoverMissing
openhands-agent-server/openhands/agent_server
   conversation_service.py110312389%178–179, 188, 215–216, 220–221, 226, 329–330, 333–334, 346–347, 361, 534–535, 553, 570, 624, 646, 653–654, 676, 726, 793, 816, 846–847, 863, 893, 897, 911, 923–926, 932–933, 942, 944, 998, 1004–1005, 1009–1010, 1018, 1045, 1051, 1145, 1151, 1156, 1162, 1170–1171, 1180–1183, 1192, 1204, 1212, 1235, 1241–1242, 1245–1247, 1274, 1320, 1413–1414, 1474, 1518–1520, 1522–1523, 1526–1527, 1547, 1661–1663, 1666–1667, 1671–1673, 1676–1677, 1681–1683, 1686–1687, 1716, 1725, 1765, 1775–1777, 1837, 1840, 1867, 1877, 1882–1885, 1899, 1910, 1921–1922, 1954, 2044, 2095, 2153, 2164–2165, 2525, 2578, 2581
openhands-agent-server/openhands/agent_server/telemetry
   factory.py46296%100, 104
   subscriber.py142795%120, 204, 218–219, 306–307, 321
TOTAL401281690358% 

Co-authored-by: openhands <openhands@all-hands.dev>
@malhotra5
malhotra5 force-pushed the oss-8687-canonical-conversation-telemetry branch from 4782a20 to aadf917 Compare August 11, 2026 03:48
@malhotra5 malhotra5 changed the title Emit canonical conversation telemetry from agent server feat: emit canonical conversation telemetry from agent server Aug 11, 2026
@all-hands-bot

Copy link
Copy Markdown
Collaborator

🤖 OpenHands is reviewing this PR.

Head commit: aadf917f8a9b1db78360bc8234e058f879ee57e8
View the conversation: https://oss-agent-canvas.ngrok.dev/conversations/117a5f6c-1bc5-4e86-baf9-5b3187072ab9

This comment was posted by an AI agent (OpenHands).

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This review was created by an AI agent (OpenHands) on behalf of the repository maintainers.

Summary

This PR renames the conversation-creation telemetry event from conversation_started to conversation_created and adds a deterministic $insert_id for PostHog retry deduplication. The renaming is well-motivated and the test updates are thorough. However, there is one material issue with the new event name that should be addressed before merge.

Risk Assessment: Medium

The missing agent_server. prefix on the new event name will cause the conversation-creation KPI to land in a different PostHog event namespace than every sibling event, breaking any existing dashboards or queries that filter on agent_server.*. This appears to be an unintentional oversight rather than a deliberate design choice, since the PR's own README update claims "all prefixed agent_server.."

Findings

1. Missing agent_server. prefix on CONVERSATION_CREATED (blocking)

CONVERSATION_CREATED = "conversation_created" (models.py:70) drops the agent_server. prefix that every other event in the EventName enum uses:

  • CONVERSATION_FINISHED = "agent_server.conversation_finished"
  • CONVERSATION_FAILED = "agent_server.conversation_failed"
  • CONVERSATION_ERROR = "agent_server.conversation_error"
  • SERVER_STARTED = "agent_server.server_started"
  • SERVER_STOPPED = "agent_server.server_stopped"
  • REQUEST_FAILED = "agent_server.request_failed"

The posthog exporter passes event.event_name directly as the PostHog event name (posthog_exporter.py:82), so this event will appear as conversation_created in PostHog rather than agent_server.conversation_created. Any existing PostHog dashboards, insights, or funnels filtering on agent_server.* will silently miss this event. The README update (line 197-199) explicitly states these events are "all prefixed agent_server." -- which is now self-contradicting for conversation_created.

If the unprefixed name is intentional and the prefix is being dropped as part of this canonicalization, the README claim should be updated and the migration should be called out in the PR description. Otherwise, this should be "agent_server.conversation_created".

2. Orphaned CONVERSATION_STARTED enum member (non-blocking)

CONVERSATION_STARTED = "agent_server.conversation_started" (models.py:69) is no longer emitted by any production code. It is only referenced in test_telemetry_sink.py:23 as a convenience for constructing arbitrary test events. Consider removing the dead enum member and updating the test helper to use a live event name (e.g., CONVERSATION_CREATED). Leaving it creates confusion about whether it is still an active event.

3. $insert_id scoped to the KPI event only (observation)

The deterministic $insert_id is set only on conversation_created, which aligns with the stated goal of deduplicating the KPI count. Other events (conversation_finished, conversation_failed, conversation_error) can also be duplicated on PostHog retry but do not receive a deterministic insert_id. This appears to be a deliberate scope decision; flagging it here so it is a conscious choice rather than an omission.

4. Insert-id determinism is per-process (observation, not a defect)

The conversation_ref used in the insert_id is derived via pseudonymize() with a per-process salt (uuid.uuid4().hex in DiagnosticEventFactory.__init__). This means the insert_id is deterministic within a single server process (sufficient for PostHog batch-retry dedup) but not across restarts. This is correct for the stated purpose -- a restarted process would not re-emit conversation_created for an existing conversation since is_new_conversation defaults to False.

Comment thread openhands-agent-server/openhands/agent_server/telemetry/models.py Outdated
Comment thread openhands-agent-server/openhands/agent_server/README.md
Co-authored-by: openhands <openhands@all-hands.dev>
@all-hands-bot

Copy link
Copy Markdown
Collaborator

🚦 CI is currently failing on this PR's latest commit.

Please fix the failing checks before OpenHands reviews it - this is re-checked automatically once you push a new commit. (A maintainer can also request @all-hands-bot as a reviewer to have it reviewed regardless of CI status.)

This is an automated check - no AI was used to generate this comment.

@malhotra5
malhotra5 merged commit 73cdfb7 into main Aug 11, 2026
45 of 47 checks passed
@malhotra5
malhotra5 deleted the oss-8687-canonical-conversation-telemetry branch August 11, 2026 19:14
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.

4 participants