rfc(decision): Prevent duplicate AI Client Spans - #155

Open
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans
Open

rfc(decision): Prevent duplicate AI Client Spans#155
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans

Conversation

@alexander-alderman-webb

@alexander-alderman-webbalexander-alderman-webb commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

@alexander-alderman-webb
alexander-alderman-webbforce-pushed the rfc/prevent-duplicate-ai-client-spans branch from 6f90149 to e2d49edCompareMarch 9, 2026 15:15

Many statistics displayed in the AI Agents Insights module are based on AI Client Spans. Statistics, including the total incurred cost, require all model calls to be instrumented with AI Client Spans exactly once. Model calls initiated by agents are always instrumented in agent libraries to support users of an agent library with a model provider not yet supported by the corresponding SDK. Conversely, "low-level" libraries of model providers are also instrumented with AI Client Spans to support users who call models outside of a supported agent framework.

Users of a supported agent framework with a supported model provider therefore generate two AI Client Spans, resulting in biased statistics in the AI Agents Insights module.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Might be helpful here to give an example of what you mean by biased statistics (e.g. double counting of tokens)


#### Pros

More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.
In some cases more information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

nit but not sure if this is universally true so I'd phrase this less definitive

└── API call
```

Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.
In some cases data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Disabling spans at the client library level results in a loss of information when the agent library's abstractions expose less information about model calls, and there is no mechanism to capture information from the client library.

Additionally, since the model abstraction used by an agent may contain user-defined code, there can be spans in between the AI Client Spans for the agent and client library. The parent-aware disabling only applies if there are no spans in between AI Client Spans in the trace hierarchy.

@nicohrubecnicohrubecMar 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

From our (js) side the most important drawback is that this solution doesn't work for our langchain use case


#### Cons

The solution introduces complexity to the SDK. An integration would mutate the attributes set on a span created by another integration when the agent and client libraries are both instrumented.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is only true for the "AI Client Scope" case right? For the boolean case I think this is only marginally more complex than the parent solution

Sign up for freeto 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.

2 participants

@alexander-alderman-webb@nicohrubec
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

rfc(decision): Prevent duplicate AI Client Spans - #155

Open
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans
Open

rfc(decision): Prevent duplicate AI Client Spans#155
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans

Conversation

@alexander-alderman-webb

@alexander-alderman-webbalexander-alderman-webb commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

@alexander-alderman-webb
alexander-alderman-webbforce-pushed the rfc/prevent-duplicate-ai-client-spans branch from 6f90149 to e2d49edCompareMarch 9, 2026 15:15

Many statistics displayed in the AI Agents Insights module are based on AI Client Spans. Statistics, including the total incurred cost, require all model calls to be instrumented with AI Client Spans exactly once. Model calls initiated by agents are always instrumented in agent libraries to support users of an agent library with a model provider not yet supported by the corresponding SDK. Conversely, "low-level" libraries of model providers are also instrumented with AI Client Spans to support users who call models outside of a supported agent framework.

Users of a supported agent framework with a supported model provider therefore generate two AI Client Spans, resulting in biased statistics in the AI Agents Insights module.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Might be helpful here to give an example of what you mean by biased statistics (e.g. double counting of tokens)


#### Pros

More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.
In some cases more information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

nit but not sure if this is universally true so I'd phrase this less definitive

└── API call
```

Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.
In some cases data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Disabling spans at the client library level results in a loss of information when the agent library's abstractions expose less information about model calls, and there is no mechanism to capture information from the client library.

Additionally, since the model abstraction used by an agent may contain user-defined code, there can be spans in between the AI Client Spans for the agent and client library. The parent-aware disabling only applies if there are no spans in between AI Client Spans in the trace hierarchy.

@nicohrubecnicohrubecMar 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

From our (js) side the most important drawback is that this solution doesn't work for our langchain use case


#### Cons

The solution introduces complexity to the SDK. An integration would mutate the attributes set on a span created by another integration when the agent and client libraries are both instrumented.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is only true for the "AI Client Scope" case right? For the boolean case I think this is only marginally more complex than the parent solution

Sign up for freeto 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.

2 participants

@alexander-alderman-webb@nicohrubec
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

rfc(decision): Prevent duplicate AI Client Spans - #155

Open
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans
Open

rfc(decision): Prevent duplicate AI Client Spans#155
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans

Conversation

@alexander-alderman-webb

@alexander-alderman-webbalexander-alderman-webb commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

@alexander-alderman-webb
alexander-alderman-webbforce-pushed the rfc/prevent-duplicate-ai-client-spans branch from 6f90149 to e2d49edCompareMarch 9, 2026 15:15

Many statistics displayed in the AI Agents Insights module are based on AI Client Spans. Statistics, including the total incurred cost, require all model calls to be instrumented with AI Client Spans exactly once. Model calls initiated by agents are always instrumented in agent libraries to support users of an agent library with a model provider not yet supported by the corresponding SDK. Conversely, "low-level" libraries of model providers are also instrumented with AI Client Spans to support users who call models outside of a supported agent framework.

Users of a supported agent framework with a supported model provider therefore generate two AI Client Spans, resulting in biased statistics in the AI Agents Insights module.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Might be helpful here to give an example of what you mean by biased statistics (e.g. double counting of tokens)


#### Pros

More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.
In some cases more information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

nit but not sure if this is universally true so I'd phrase this less definitive

└── API call
```

Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.
In some cases data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Disabling spans at the client library level results in a loss of information when the agent library's abstractions expose less information about model calls, and there is no mechanism to capture information from the client library.

Additionally, since the model abstraction used by an agent may contain user-defined code, there can be spans in between the AI Client Spans for the agent and client library. The parent-aware disabling only applies if there are no spans in between AI Client Spans in the trace hierarchy.

@nicohrubecnicohrubecMar 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

From our (js) side the most important drawback is that this solution doesn't work for our langchain use case


#### Cons

The solution introduces complexity to the SDK. An integration would mutate the attributes set on a span created by another integration when the agent and client libraries are both instrumented.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is only true for the "AI Client Scope" case right? For the boolean case I think this is only marginally more complex than the parent solution

Sign up for freeto 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.

2 participants

@alexander-alderman-webb@nicohrubec
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

rfc(decision): Prevent duplicate AI Client Spans - #155

Open
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans
Open

rfc(decision): Prevent duplicate AI Client Spans#155
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans

Conversation

@alexander-alderman-webb

@alexander-alderman-webbalexander-alderman-webb commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

@alexander-alderman-webb
alexander-alderman-webbforce-pushed the rfc/prevent-duplicate-ai-client-spans branch from 6f90149 to e2d49edCompareMarch 9, 2026 15:15

Many statistics displayed in the AI Agents Insights module are based on AI Client Spans. Statistics, including the total incurred cost, require all model calls to be instrumented with AI Client Spans exactly once. Model calls initiated by agents are always instrumented in agent libraries to support users of an agent library with a model provider not yet supported by the corresponding SDK. Conversely, "low-level" libraries of model providers are also instrumented with AI Client Spans to support users who call models outside of a supported agent framework.

Users of a supported agent framework with a supported model provider therefore generate two AI Client Spans, resulting in biased statistics in the AI Agents Insights module.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Might be helpful here to give an example of what you mean by biased statistics (e.g. double counting of tokens)


#### Pros

More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.
In some cases more information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

nit but not sure if this is universally true so I'd phrase this less definitive

└── API call
```

Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.
In some cases data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Disabling spans at the client library level results in a loss of information when the agent library's abstractions expose less information about model calls, and there is no mechanism to capture information from the client library.

Additionally, since the model abstraction used by an agent may contain user-defined code, there can be spans in between the AI Client Spans for the agent and client library. The parent-aware disabling only applies if there are no spans in between AI Client Spans in the trace hierarchy.

@nicohrubecnicohrubecMar 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

From our (js) side the most important drawback is that this solution doesn't work for our langchain use case


#### Cons

The solution introduces complexity to the SDK. An integration would mutate the attributes set on a span created by another integration when the agent and client libraries are both instrumented.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is only true for the "AI Client Scope" case right? For the boolean case I think this is only marginally more complex than the parent solution

Sign up for freeto 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.

2 participants

@alexander-alderman-webb@nicohrubec
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

rfc(decision): Prevent duplicate AI Client Spans - #155

Open
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans
Open

rfc(decision): Prevent duplicate AI Client Spans#155
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans

Conversation

@alexander-alderman-webb

@alexander-alderman-webbalexander-alderman-webb commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

@alexander-alderman-webb
alexander-alderman-webbforce-pushed the rfc/prevent-duplicate-ai-client-spans branch from 6f90149 to e2d49edCompareMarch 9, 2026 15:15

Many statistics displayed in the AI Agents Insights module are based on AI Client Spans. Statistics, including the total incurred cost, require all model calls to be instrumented with AI Client Spans exactly once. Model calls initiated by agents are always instrumented in agent libraries to support users of an agent library with a model provider not yet supported by the corresponding SDK. Conversely, "low-level" libraries of model providers are also instrumented with AI Client Spans to support users who call models outside of a supported agent framework.

Users of a supported agent framework with a supported model provider therefore generate two AI Client Spans, resulting in biased statistics in the AI Agents Insights module.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Might be helpful here to give an example of what you mean by biased statistics (e.g. double counting of tokens)


#### Pros

More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.
In some cases more information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

nit but not sure if this is universally true so I'd phrase this less definitive

└── API call
```

Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.
In some cases data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Disabling spans at the client library level results in a loss of information when the agent library's abstractions expose less information about model calls, and there is no mechanism to capture information from the client library.

Additionally, since the model abstraction used by an agent may contain user-defined code, there can be spans in between the AI Client Spans for the agent and client library. The parent-aware disabling only applies if there are no spans in between AI Client Spans in the trace hierarchy.

@nicohrubecnicohrubecMar 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

From our (js) side the most important drawback is that this solution doesn't work for our langchain use case


#### Cons

The solution introduces complexity to the SDK. An integration would mutate the attributes set on a span created by another integration when the agent and client libraries are both instrumented.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is only true for the "AI Client Scope" case right? For the boolean case I think this is only marginally more complex than the parent solution

Sign up for freeto 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.

2 participants

@alexander-alderman-webb@nicohrubec
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

rfc(decision): Prevent duplicate AI Client Spans - #155

Open
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans
Open

rfc(decision): Prevent duplicate AI Client Spans#155
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans

Conversation

@alexander-alderman-webb

@alexander-alderman-webbalexander-alderman-webb commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

@alexander-alderman-webb
alexander-alderman-webbforce-pushed the rfc/prevent-duplicate-ai-client-spans branch from 6f90149 to e2d49edCompareMarch 9, 2026 15:15

Many statistics displayed in the AI Agents Insights module are based on AI Client Spans. Statistics, including the total incurred cost, require all model calls to be instrumented with AI Client Spans exactly once. Model calls initiated by agents are always instrumented in agent libraries to support users of an agent library with a model provider not yet supported by the corresponding SDK. Conversely, "low-level" libraries of model providers are also instrumented with AI Client Spans to support users who call models outside of a supported agent framework.

Users of a supported agent framework with a supported model provider therefore generate two AI Client Spans, resulting in biased statistics in the AI Agents Insights module.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Might be helpful here to give an example of what you mean by biased statistics (e.g. double counting of tokens)


#### Pros

More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.
In some cases more information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

nit but not sure if this is universally true so I'd phrase this less definitive

└── API call
```

Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.
In some cases data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Disabling spans at the client library level results in a loss of information when the agent library's abstractions expose less information about model calls, and there is no mechanism to capture information from the client library.

Additionally, since the model abstraction used by an agent may contain user-defined code, there can be spans in between the AI Client Spans for the agent and client library. The parent-aware disabling only applies if there are no spans in between AI Client Spans in the trace hierarchy.

@nicohrubecnicohrubecMar 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

From our (js) side the most important drawback is that this solution doesn't work for our langchain use case


#### Cons

The solution introduces complexity to the SDK. An integration would mutate the attributes set on a span created by another integration when the agent and client libraries are both instrumented.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is only true for the "AI Client Scope" case right? For the boolean case I think this is only marginally more complex than the parent solution

Sign up for freeto 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.

2 participants

@alexander-alderman-webb@nicohrubec
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

rfc(decision): Prevent duplicate AI Client Spans - #155

Open
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans
Open

rfc(decision): Prevent duplicate AI Client Spans#155
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans

Conversation

@alexander-alderman-webb

@alexander-alderman-webbalexander-alderman-webb commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

@alexander-alderman-webb
alexander-alderman-webbforce-pushed the rfc/prevent-duplicate-ai-client-spans branch from 6f90149 to e2d49edCompareMarch 9, 2026 15:15

Many statistics displayed in the AI Agents Insights module are based on AI Client Spans. Statistics, including the total incurred cost, require all model calls to be instrumented with AI Client Spans exactly once. Model calls initiated by agents are always instrumented in agent libraries to support users of an agent library with a model provider not yet supported by the corresponding SDK. Conversely, "low-level" libraries of model providers are also instrumented with AI Client Spans to support users who call models outside of a supported agent framework.

Users of a supported agent framework with a supported model provider therefore generate two AI Client Spans, resulting in biased statistics in the AI Agents Insights module.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Might be helpful here to give an example of what you mean by biased statistics (e.g. double counting of tokens)


#### Pros

More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.
In some cases more information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

nit but not sure if this is universally true so I'd phrase this less definitive

└── API call
```

Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.
In some cases data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Disabling spans at the client library level results in a loss of information when the agent library's abstractions expose less information about model calls, and there is no mechanism to capture information from the client library.

Additionally, since the model abstraction used by an agent may contain user-defined code, there can be spans in between the AI Client Spans for the agent and client library. The parent-aware disabling only applies if there are no spans in between AI Client Spans in the trace hierarchy.

@nicohrubecnicohrubecMar 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

From our (js) side the most important drawback is that this solution doesn't work for our langchain use case


#### Cons

The solution introduces complexity to the SDK. An integration would mutate the attributes set on a span created by another integration when the agent and client libraries are both instrumented.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is only true for the "AI Client Scope" case right? For the boolean case I think this is only marginally more complex than the parent solution

Sign up for freeto 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.

2 participants

@alexander-alderman-webb@nicohrubec
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

rfc(decision): Prevent duplicate AI Client Spans - #155

Open
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans
Open

rfc(decision): Prevent duplicate AI Client Spans#155
alexander-alderman-webb wants to merge 3 commits into
mainfrom
rfc/prevent-duplicate-ai-client-spans

Conversation

@alexander-alderman-webb

@alexander-alderman-webbalexander-alderman-webb commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

@alexander-alderman-webb
alexander-alderman-webbforce-pushed the rfc/prevent-duplicate-ai-client-spans branch from 6f90149 to e2d49edCompareMarch 9, 2026 15:15

Many statistics displayed in the AI Agents Insights module are based on AI Client Spans. Statistics, including the total incurred cost, require all model calls to be instrumented with AI Client Spans exactly once. Model calls initiated by agents are always instrumented in agent libraries to support users of an agent library with a model provider not yet supported by the corresponding SDK. Conversely, "low-level" libraries of model providers are also instrumented with AI Client Spans to support users who call models outside of a supported agent framework.

Users of a supported agent framework with a supported model provider therefore generate two AI Client Spans, resulting in biased statistics in the AI Agents Insights module.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Might be helpful here to give an example of what you mean by biased statistics (e.g. double counting of tokens)


#### Pros

More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
More information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.
In some cases more information used to populate the attributes of AI Client Spans is available in the client library than in the agent library abstraction.

nit but not sure if this is universally true so I'd phrase this less definitive

└── API call
```

Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
Some data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.
In some cases data exposed by the client library is not available at the agent's model abstraction level. For example, the concrete response model used to populate the `gen_ai.response.model` attribute is always available in the `openai` package, but never returned by the `Model` abstraction used by agents in the `openai-agents` package.

Disabling spans at the client library level results in a loss of information when the agent library's abstractions expose less information about model calls, and there is no mechanism to capture information from the client library.

Additionally, since the model abstraction used by an agent may contain user-defined code, there can be spans in between the AI Client Spans for the agent and client library. The parent-aware disabling only applies if there are no spans in between AI Client Spans in the trace hierarchy.

@nicohrubecnicohrubecMar 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

From our (js) side the most important drawback is that this solution doesn't work for our langchain use case


#### Cons

The solution introduces complexity to the SDK. An integration would mutate the attributes set on a span created by another integration when the agent and client libraries are both instrumented.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is only true for the "AI Client Scope" case right? For the boolean case I think this is only marginally more complex than the parent solution

Sign up for freeto 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.

2 participants

@alexander-alderman-webb@nicohrubec