OpenHands / OpenHands/enterprise

[Bug]: get git repo identity reliably into Laminar traces

Open
#58 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Python
Stars
4
Forks
2
Avg merge
1d 22h
Merged PRs (30d)
101

Description

Goal

Laminar traces should reliably carry git repo/branch/commit identity for any conversation that ends up touching a repo — not just conversations where a repo was pre-selected at creation. Today they don't, for two compounding reasons below. Both need fixing to actually achieve this.

Problem 1: the metadata that IS collected gets silently discarded (mechanical bug)

In openhands/app_server/app_conversation/live_status_app_conversation_service.py, the observability_metadata dict built by _build_observability_context (added in OpenHands/OpenHands#14431) is immediately overwritten two lines later by a reassignment from _build_observability_metadata (added in OpenHands/OpenHands#15059) — at both conversation-request builders (the regular OpenHands path and the ACP path). Only observability_tags from the first call survives.

_build_start_conversation_request_for_user (~line 1801):

observability_metadata, observability_tags = self._build_observability_context(
    conversation_id,
    agent_kind='openhands',
    selected_repository=selected_repository,
    selected_branch=selected_branch,
    git_provider=git_provider,
)
...
observability_metadata = await self._build_observability_metadata(   # <-- clobbers the line above
    remote_workspace,
    project_dir,
    selected_repository,
    selected_branch,
    git_provider,
)
create_kwargs: dict[str, Any] = {'agent': agent, 'user_id': laminar_user_id}
if observability_metadata:
    create_kwargs['observability_metadata'] = observability_metadata
if observability_tags:
    create_kwargs['observability_tags'] = observability_tags

The identical pattern repeats in _build_acp_start_conversation_request (~line 2057-2097) for the ACP path.

_build_observability_context's metadata dict (app, conversation_id, agent_kind, repo_name, selected_branch, git_provider) is computed and then thrown away — it never reaches create_kwargs['observability_metadata']. Only its tags return value (app:openhands, agent_kind:..., repo:..., branch:..., git_provider:...) makes it through. The observability_metadata actually sent to Laminar ends up exclusively _build_observability_metadata's output (repo, branch, git_provider, commit), missing app/conversation_id/agent_kind.

Problem 2: even fixed, metadata only exists for repo-preselected conversations

_build_observability_metadata's repo/branch/git_provider/commit are all derived from selected_repository/selected_branch — the structured field passed at conversation creation (repo-picker flow). For a conversation started from scratch where the agent clones a repo itself in response to a chat message (selected_repository: null at creation — confirmed the dominant real-world flow via production trace analysis on infra#1454), this metadata stays empty for the whole conversation, even after the agent has cloned and is actively working in a repo. Fixing Problem 1 alone does not close this gap — most real conversations would still show no git identity in Laminar.

Suggested fix

  1. Immediate: merge the two metadata dicts instead of one clobbering the other (e.g. metadata = {**context_metadata, **resolved_metadata}, or fold _build_observability_context's app/conversation_id/agent_kind fields into _build_observability_metadata and drop the duplicate call), at both call sites.
  2. To actually meet the goal: populate/update git identity for conversations where the repo shows up after conversation start. Laminar metadata is currently only set once, at trace/request creation. Two directions worth weighing:
    • Reuse the live git-probe the workspace-archive endpoint already does (software-agent-sdk#3932, GET /api/file/archive's X-Archive-Repo-Remote/-Branch/-Head-Commit headers) to backfill/update trace metadata at archive time (pause/delete) — the only point today that already does a live probe outside of pre-agent setup.
    • Or hook into the agent's action/event stream to detect the first git clone/repo materialization and update trace metadata then — more general, more invasive.

Introduced by OpenHands/OpenHands#14431 landing on top of OpenHands/OpenHands#15059 (merged 2026-07-01 / 2026-07-09 respectively); Problem 1 didn't exist before either PR individually. Problem 2 predates both — OpenHands/OpenHands#15059 already had it, OpenHands/OpenHands#14431 didn't change it.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in openhands/app_server/app_conversation/live_status_app_conversation_service.py, reading _build_observability_context, _build_observability_metadata, _build_start_conversation_request_for_user, and _build_acp_start_conversation_request. Compare both request builders and inspect the GET /api/file/archive live git-probe headers. Done means Laminar retains the combined metadata and receives git identity for repositories discovered after conversation creation.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
observability
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.