Skip to content

Add OpenClaw User-Agent header to all outbound HTTP requests#51570

Open
SidU wants to merge 2 commits intoopenclaw:mainfrom
SidU:claude/teams-plugin-user-agent-Xx0fM
Open

Add OpenClaw User-Agent header to all outbound HTTP requests#51570
SidU wants to merge 2 commits intoopenclaw:mainfrom
SidU:claude/teams-plugin-user-agent-Xx0fM

Conversation

@SidU
Copy link
Copy Markdown
Contributor

@SidU SidU commented Mar 21, 2026

Summary

  • Problem: Outbound HTTP requests to Microsoft Graph and Teams APIs lack identifying User-Agent headers, making it difficult to track OpenClaw usage and debug integration issues.
  • Why it matters: User-Agent headers are standard HTTP practice for identifying clients; they enable better observability, debugging, and usage tracking across Microsoft services.
  • What changed:
    • Added buildUserAgent() function that constructs OpenClaw/<version> headers from the MSTeams runtime
    • Injected User-Agent headers into all Graph API calls (graph.ts, graph-upload.ts, attachments/graph.ts)
    • Injected User-Agent headers into file consent uploads (file-consent.ts)
    • Extended CloudAdapter subclass to inject User-Agent into all ConnectorClient instances (both inbound webhook replies and proactive messages)
    • Added comprehensive unit tests for User-Agent generation and header injection
  • What did NOT change: No changes to authentication, token handling, or API contracts; User-Agent is purely informational.

Closes #51568

Change Type

  • Feature
  • Refactor required for the fix

Scope

  • Integrations
  • API / contracts

Linked Issue/PR

  • Closes (if applicable, update with actual issue number)

User-visible / Behavior Changes

None. User-Agent headers are transparent to end users; they only appear in HTTP request metadata visible to Microsoft services and network logs.

Security Impact

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No (same calls, just with additional header)
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • N/A (header injection is transparent)

Steps

  1. Run unit tests: npm test -- user-agent.test.ts graph.user-agent.test.ts
  2. Verify tests pass and User-Agent header is correctly formatted as OpenClaw/<version>
  3. Verify caller-provided User-Agent headers can override the default (tested in graph.user-agent.test.ts)

Expected

  • buildUserAgent() returns OpenClaw/2026.3.19 (or current runtime version)
  • All Graph API calls include User-Agent: OpenClaw/<version> header
  • All ConnectorClient instances created by CloudAdapter include the User-Agent header
  • Custom User-Agent headers from callers are respected and not overridden

Actual

  • All tests pass
  • User-Agent header is consistently injected across all outbound requests
  • Fallback to OpenClaw/unknown when runtime is not initialized

Evidence

  • Failing test/log before + passing after
    • Added user-agent.test.ts with 3 test cases covering normal operation, version reflection, and error handling
    • Added graph.user-agent.test.ts with 2 test cases covering default User-Agent injection and caller override behavior
    • All tests pass with the implementation

Human Verification

  • Verified scenarios:

    • User-Agent header is correctly formatted as OpenClaw/<version>
    • Header is injected into Graph API calls (GET, POST, PUT)
    • Header is injected into ConnectorClient creation for both inbound and proactive messages
    • Caller-provided headers override the default User-Agent
    • Runtime initialization errors gracefully fall back to unknown version
  • Edge cases checked:

    • MSTeams runtime not initialized (throws error → fallback to unknown)
    • Custom User-Agent headers from callers are preserved
    • Header propagation works with both createConnectorClient and createConnectorClientWithIdentity
  • What you did NOT verify:

    • End-to-end integration with actual Microsoft Teams/Graph services (covered by existing integration tests)
    • Performance impact (negligible—single string concatenation)

Compatibility / Migration

  • Backward compatible? Yes (purely additive; no breaking changes)
  • Config/env changes? No
  • Migration

https://claude.ai/code/session_019xsguY8tjCjHwwvUu8zxjj

Adds "OpenClaw/<version>" User-Agent header to every outbound HTTP
request the Teams plugin makes to Microsoft services:

- Graph API calls (fetchGraphJson, graph-upload, attachments/graph)
- Bot Framework SDK connector client (via CloudAdapter subclass that
  injects the header into both inbound webhook replies and proactive
  messages via continueConversation)
- File consent uploads

The version is read from the plugin runtime (PluginRuntime.version).

https://claude.ai/code/session_019xsguY8tjCjHwwvUu8zxjj
@SidU SidU self-assigned this Mar 21, 2026
@openclaw-barnacle openclaw-barnacle bot added channel: msteams Channel integration: msteams size: S maintainer Maintainer-authored PR labels Mar 21, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 21, 2026

Greptile Summary

This PR adds OpenClaw/<version> User-Agent headers to all outbound HTTP requests made to Microsoft Graph and Teams APIs, using a new buildUserAgent() helper that reads the version from the MSTeams runtime with a graceful fallback to "unknown". The change is purely additive and well-tested.

Two items warrant attention before merging:

  • SharePoint fetchImpl gap (attachments/graph.ts, ~line 284): The custom fetch callback used for SharePoint share-link downloads reconstructs its own Headers object and only sets Authorization — the User-Agent header is never added, leaving this one outbound Graph call without the header while every other call-site was updated.
  • propagation.override() priority in sdk.ts: The CloudAdapter subclass calls propagation.override({ "User-Agent": buildUserAgent() }) on the incoming headers object (when present). Depending on whether HeaderPropagation.override overwrites or only fills-in missing values, this could silently replace a caller-supplied User-Agent, which is the opposite of the "caller wins" contract demonstrated in graph.ts and tested in graph.user-agent.test.ts.

Confidence Score: 4/5

  • Safe to merge after confirming the SharePoint fetch callback and HeaderPropagation.override semantics.
  • The implementation is clean, well-tested, and purely additive. The SharePoint fetchImpl omission is a concrete missed injection that contradicts the PR's "all Graph API calls" claim, but it is low-severity (no auth or data-loss risk). The HeaderPropagation.override priority question is a semantic concern that needs a quick check against the SDK docs rather than a code rewrite.
  • extensions/msteams/src/attachments/graph.ts (SharePoint fetchImpl) and extensions/msteams/src/sdk.ts (HeaderPropagation.override semantics)

Comments Outside Diff (1)

  1. extensions/msteams/src/attachments/graph.ts, line 282-287 (link)

    P2 Missing User-Agent in SharePoint fetchImpl callback

    The fetchImpl callback passed to downloadAndStoreMSTeamsRemoteMedia sets Authorization but omits User-Agent. This is the only remaining outbound Graph call in this file that doesn't carry the header, inconsistent with all the other updated call-sites.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: extensions/msteams/src/attachments/graph.ts
    Line: 282-287
    
    Comment:
    **Missing User-Agent in SharePoint `fetchImpl` callback**
    
    The `fetchImpl` callback passed to `downloadAndStoreMSTeamsRemoteMedia` sets `Authorization` but omits `User-Agent`. This is the only remaining outbound Graph call in this file that doesn't carry the header, inconsistent with all the other updated call-sites.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/msteams/src/attachments/graph.ts
Line: 282-287

Comment:
**Missing User-Agent in SharePoint `fetchImpl` callback**

The `fetchImpl` callback passed to `downloadAndStoreMSTeamsRemoteMedia` sets `Authorization` but omits `User-Agent`. This is the only remaining outbound Graph call in this file that doesn't carry the header, inconsistent with all the other updated call-sites.

```suggestion
            fetchImpl: async (input, init) => {
              const requestUrl = resolveRequestUrl(input);
              const headers = new Headers(init?.headers);
              headers.set("User-Agent", buildUserAgent());
              headers.set("Authorization", `Bearer ${accessToken}`);
              return await safeFetch({
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/msteams/src/sdk.ts
Line: 39-41

Comment:
**`propagation.override()` may always clobber caller-supplied User-Agent**

The pattern here first takes the existing `headers` (if any) and then unconditionally calls `propagation.override({ "User-Agent": buildUserAgent() })`. If `HeaderPropagation.override` truly overwrites existing values, any caller that passes a custom User-Agent inside their `headers` argument will silently have it replaced.

This is the opposite of what `graph.ts` does (where `...params.headers` is spread after the default, so callers can override). Please verify that `HeaderPropagation.override` only sets the value when it is absent, or invert the priority to match the `graph.ts` convention — e.g. check whether the header is already present before calling `override`.

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: "msteams: add OpenCla..."

- Add User-Agent header to SharePoint fetchImpl callback (was the only
  remaining outbound Graph call without it)
- Guard CloudAdapter User-Agent injection so caller-supplied headers
  are not clobbered by propagation.override()

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@SidU
Copy link
Copy Markdown
Contributor Author

SidU commented Mar 21, 2026

Both items fixed in 7ba1f97:

  1. SharePoint fetchImpl gap — added User-Agent header to the SharePoint share-link download callback.
  2. propagation.override() priority — now guarded with a propagation.get("User-Agent") check so caller-supplied headers win, matching the graph.ts convention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: msteams Channel integration: msteams maintainer Maintainer-authored PR size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

msteams: add OpenClaw User-Agent header to Microsoft backend HTTP calls

2 participants