June 17th, 2026
0 reactions

When your agent extensions fight each other

Principal Developer Advocate

This is the fourth article in a series about Agent Experience (AX): the practice of making AI coding agents work correctly with your technology. The series covers what you can and can’t control in the agent stack, how to measure whether your extensions are helping or hurting, and how to iterate toward better outcomes.这是关于代理体验(AX)系列的第四篇文章:让 AI 编码代理能够正确使用您的技术的实践。该系列涵盖了您在代理堆栈中可以控制和不能控制的内容,如何衡量您的扩展是帮助还是阻碍,以及如何迭代以获得更好的结果。

You shipped your extension, measured it, confirmed it creates lift. Then a developer installs it alongside 14 other extensions, and outcomes get worse. Not because your extension is broken, but because extensions don’t exist in isolation: they compete.您发布了扩展,进行了测量,确认它带来了提升。然后一位开发者在 14 个其他扩展一起安装后,结果变差了。并不是因为您的扩展坏了,而是因为扩展并非孤立存在:它们会相互竞争。

In the previous article, we covered how to measure whether a single extension creates lift or drag. That measurement assumed a clean environment: your extension, and nothing else. Real developer workspaces don’t look like that. Real workspaces have MCP servers for their cloud provider, instruction files from their team, skills from their framework, and whatever’s trending on social this week. The question really isn’t whether your extension works, it’s whether it works well with others.在上一篇文章中,我们介绍了如何衡量单个扩展是提升还是拖累。该测量假设了一个干净的环境:只有您的扩展,别无他物。真实的开发者工作空间并非如此。真实的工作空间会有云提供商的 MCP 服务器、团队的指令文件、框架的技能,以及本周社交媒体上流行的内容。真正的问题不是您的扩展是否有效,而是它是否能与其他扩展良好协作。

More extensions, worse outcomes更多扩展,结果更差 复制链接

It seems like extensions should be additive: extension A improves authentication code, extension B improves database queries. Install both, get better auth and better queries. Right? Not quite.看起来扩展应该是可叠加的:扩展 A 改进身份验证代码,扩展 B 改进数据库查询。两者都装上,身份验证更好,查询更好。对吧?其实并非如此。

Every extension consumes tokens in the context window just by being installed. Tool descriptions and skill definitions take up space before you even type a prompt. A single MCP server with 8 tools might add 2,000 tokens of tool descriptions. Five MCP servers? That’s 10,000 tokens of tool descriptions alone, and you haven’t asked anything yet. The context window is a fixed budget. Every token spent on tool descriptions is a token not spent on workspace context or conversation history. Install enough extensions and the harness starts making cuts: summarizing tool descriptions, dropping tools it deems irrelevant, and truncating whatever doesn’t fit. Your carefully written tool description might get compressed into something the model can barely interpret.每个扩展仅仅因为被安装就会在上下文窗口中消耗 token。工具描述和技能定义会占用空间,甚至在您输入提示之前。一个包含 8 个工具的 MCP 服务器可能会增加约 2,000 个 token 的工具描述。五个 MCP 服务器?仅工具描述就要 10,000 个 token,您甚至还没有提出任何请求。上下文窗口的容量是固定的。每个用于工具描述的 token 都是未用于工作空间上下文或对话历史的 token。安装足够多的扩展后,系统会开始削减:对工具描述进行摘要、丢弃它认为不相关的工具,并截断不适合的内容。您精心编写的工具描述可能会被压缩成模型几乎无法解释的形式。

Two stacked bars representing the same fixed-size context window. The left bar, labeled "2 extensions," has a small tool-descriptions segment and a large workspace-context segment. The right bar, labeled "10 extensions," shows tool descriptions dominating the window while workspace context shrinks to a sliver.

But it’s not just about space. Every token in the context changes the path the model takes. The model doesn’t process your extension’s content in isolation and then process the next one separately. It attends to everything at once. Add a database extension next to your auth extension, and both extensions produce different output than either would alone, even if they have nothing to do with each other. The mere presence of unrelated tool descriptions shifts the model’s attention and changes the output.但这不仅仅是空间问题。上下文中的每个 token 都会改变模型的路径。模型不会先单独处理您的扩展内容再处理下一个,而是一次性关注所有内容。把一个数据库扩展放在身份验证扩展旁边,两者的输出都会与单独使用时不同,即使它们之间没有任何关联。无关工具描述的存在会转移模型的注意力并改变输出。

We’ve measured this directly: the same extension that produces consistent lift in isolation can produce drag with even one other extension present. Not because the extension changed, but because the environment around it did.我们已经直接测量过:在单独使用时能够持续提升的同一扩展,在出现另一个扩展时可能会产生拖累。这并不是因为扩展本身改变了,而是因为其周围的环境改变了。

Three ways extensions conflict扩展冲突的三种方式 复制链接

Not all composition problems are about token budgets, though. Extensions can actively interfere with each other in ways that are harder to spot.并非所有的组合问题都与 token 预算有关。扩展之间还可能以更难发现的方式相互干扰。

Vocabulary collisions词汇冲突 复制链接

Two extensions describe their tools using similar language. Your tool says “manage authentication settings”, another tool says “configure identity and access.” The developer asks “set up auth for my app.” Both tools match the intent, the model picks one, and it might not be yours.两个扩展使用相似的语言描述它们的工具。您的工具说“管理身份验证设置”,另一个工具说“配置身份和访问”。开发者请求“为我的应用设置身份验证”。两个工具都匹配意图,模型会选一个,而可能不是您的。

A developer prompt reading "set up auth for my app" at the top, with two arrows branching down to two tool cards: "manage authentication settings" on the left and "configure identity and access" on the right. A dashed arrow from the prompt points to the right card, indicating the model picked the wrong tool.

How would you even debug that? The developer sees wrong output and blames the model. But it’s not a bug in either extension, it’s an emergent property of putting two tools with overlapping vocabulary into the same context. The model doesn’t know which one the developer means, and it can’t ask (most harnesses don’t support clarifying questions for tool selection). It makes a choice based on factors you can’t see such as context position and training data associations. What’s more, that choice might change between runs.您该如何调试?开发者看到错误输出并指责模型。但这既不是任一扩展的 bug,而是将两个词汇重叠的工具放入同一上下文后产生的涌现属性。模型不知道开发者指的是哪一个,也无法提问(大多数系统不支持针对工具选择的澄清问题)。它会基于您看不到的因素做出选择,例如上下文位置和训练数据关联。更糟的是,这种选择在不同运行之间可能会变化。

Guidance conflicts指导冲突 复制链接

Extensions inject guidance through tool descriptions and skill definitions. The agent also picks up instruction files (.github/copilot-instructions.md, AGENTS.md, .instructions.md) in the repo. Both end up in the same context window, and neither knows the other exists.扩展通过工具描述和技能定义注入指导。代理还会读取仓库中的指令文件(.github/copilot-instructions.md、AGENTS.md、.instructions.md)。它们都出现在同一上下文窗口中,且彼此并不知道对方的存在。

The collision happens when an extension’s guidance contradicts the repo’s instructions. Your extension’s tool description says “always use the v3 SDK.” The team’s copilot-instructions.md says “we use the v2 SDK for legacy compatibility.” Which one wins? The model sees both, and the outcome depends on context ordering and phrasing strength, filtered through whatever the model’s training data says about the technology. The result is unpredictable, and it can flip between runs.冲突发生在扩展的指导与仓库指令相矛盾时。您的扩展工具描述写着“始终使用 v3 SDK”。团队的 copilot-instructions.md 则写着“我们使用 v2 SDK 以保持向后兼容”。哪一个生效?模型看到两者,结果取决于上下文顺序和措辞强度,以及模型训练数据对该技术的看法。结果不可预测,且在不同运行之间可能会翻转。

And it happens between extensions too. Two extensions that both provide guidance on authentication patterns, each assuming it’s the only authority. The model gets contradictory instructions with no way to tell which one matters.这同样会在扩展之间发生。两个都提供身份验证模式指导的扩展,各自假设自己是唯一的权威。模型收到相互矛盾的指令,却无法判断哪一个更重要。

Resource competition资源竞争 复制链接

Two scenarios side by side. On the left, two MCP servers both point to a "project setup" task. On the right, three skills all point to a "deploy" task. Arrows show multiple tools competing to handle the same request.

Some extensions don’t conflict semantically but compete for the same agent behavior. For example, two MCP servers that both want to be called for “project setup,” or three skills that all trigger on “deploy.” The model might call all of them (burning tokens and turns), call the wrong one, or call one and assume it covered the others.有些扩展在语义上并不冲突,但会争夺相同的代理行为。例如,两个 MCP 服务器都想在“项目设置”时被调用,或三个技能都在“部署”时触发。模型可能会调用全部(消耗 token 和回合),调用错误的那个,或只调用一个并假设已经覆盖了其他。

And then there’s the subtle version: two tools return complementary but overlapping information. The model gets a detailed API reference from one tool and a quickstart guide from another. Both are accurate and relevant, but together they consume 6,000 tokens and the model has to reconcile two different framings of the same concept. It might merge them correctly, pick one and ignore the other, or get confused and generate code that mixes patterns from both leaving you with broken code.还有一种微妙的情况:两个工具返回互补但重叠的信息。模型从一个工具得到详细的 API 参考,从另一个工具得到快速入门指南。两者都准确且相关,但合计消耗 6,000 个 token,模型必须调和同一概念的两种不同表述。它可能会正确合并,挑选其一而忽略另一,或混乱地生成混合两种模式的代码,导致代码损坏。

The composition tax组合税 复制链接

Even when extensions don’t conflict at all, each one has a cost. Every installed extension takes up space in the context window and adds potential tool calls the model has to evaluate. This is the composition tax: the overhead of having extensions present, whether they’re used or not.即使扩展之间没有任何冲突,每个扩展也都有成本。每个已安装的扩展都会占用上下文窗口空间,并增加模型需要评估的潜在工具调用。这就是组合税:扩展存在的开销,无论是否被实际使用。

Here’s what that looks like in practice. You install five extensions. You ask a question that’s relevant to only one of them. The model still has to read all five tool descriptions to decide which one to call, spending tokens and processing time on four irrelevant tools. Sometimes it calls one that isn’t even relevant because its description seems related, wasting a turn and injecting irrelevant content into the context for the rest of the session.下面是实际情况。您安装了五个扩展。您提出一个只与其中一个相关的问题。模型仍需读取全部五个工具描述以决定调用哪一个,因而在四个无关工具上消耗 token 和处理时间。有时它会因为某个描述看起来相关而调用一个根本不相关的工具,浪费一次回合并向会话其余部分注入无关内容。

“Install everything, let the agent figure it out” is a losing strategy. Every extension you add has a marginal cost, and past a certain threshold, the cumulative cost exceeds the benefit.“安装所有东西,让代理自行决定”是一种失败的策略。每添加一个扩展都会产生边际成本,超过某个阈值后,总成本会超过收益。

Measuring net lift衡量净提升 复制链接

In the third article, we measured lift by comparing a baseline (no extensions) against a single extension. Composition measurement extends this to the full stack.在第三篇文章中,我们通过将基线(无扩展)与单一扩展进行比较来衡量提升。组合测量则将此扩展到完整堆栈。

The additive approach加法方法 复制链接

Start with your baseline (no extensions). Add one extension at a time and measure outcomes at each step:从基线(无扩展)开始。一次添加一个扩展,并在每一步测量结果:

A horizontal sequence of stacked bars, each one segment taller than the last: Baseline, then plus Extension A, plus B, plus C. The bar at plus C drops in height, with a callout reading "Composition problem here." Arrows between bars are labeled "delta outcome."

  1. Baseline: no extensions基线:无扩展
  2. +Extension A: measure+扩展 A:测量
  3. +Extension A +Extension B: measure+扩展 A +扩展 B:测量
  4. +Extension A +Extension B +Extension C: measure+扩展 A +扩展 B +扩展 C:测量

At each step, you’re asking: did outcomes improve, stay the same, or degrade, and at what cost? If adding Extension C to the stack causes outcomes to drop, you’ve found a composition problem, but you don’t yet know why.在每一步,您都在问:结果是改善、保持不变还是下降,且代价是多少?如果将扩展 C 加入堆栈导致结果下降,您已经发现了组合问题,但尚未知道原因。

Isolating the cause定位原因 复制链接

When you see degradation, run the failing combination with one extension removed at a time:当出现下降时,逐一移除一个扩展来运行出现问题的组合:

  • Extension A + Extension C (without B): does the problem persist?扩展 A + 扩展 C(不含 B):问题仍然存在吗?
  • Extension B + Extension C (without A): does the problem persist?扩展 B + 扩展 C(不含 A):问题仍然存在吗?
  • Extension C alone: does it produce lift?仅扩展 C:它能产生提升吗?

If Extension C produces lift alone but drag when combined with Extension A, you have a pairwise conflict. If Extension C produces drag whenever the total extension count exceeds a threshold, you have a token budget problem.如果扩展 C 单独能产生提升,但与扩展 A 组合时产生拖累,则存在成对冲突。如果只要扩展总数超过阈值就出现拖累,则是 token 预算问题。

The distinction matters because the fix is different. A pairwise conflict means the two extensions are interfering semantically, whether through overlapping descriptions or conflicting instructions. A token budget problem means the context window is saturated and adding anything causes degradation. You fix a conflict by changing what extensions say. You fix saturation by reducing what extensions include.区分这两者很重要,因为修复方式不同。成对冲突意味着两个扩展在语义上相互干扰,无论是描述重叠还是指令冲突。token 预算问题则意味着上下文窗口已饱和,任何新增都会导致性能下降。解决冲突需要修改扩展的描述,解决饱和则需要减少扩展包含的内容。

Net lift净提升 复制链接

The metric that matters for composition is net lift: the difference between your full extension stack and the baseline.衡量组合效果的关键指标是净提升:完整扩展堆栈的结果与基线之间的差值。

Net lift = (outcome with all extensions) – (outcome with no extensions)净提升 =(所有扩展的结果)–(无扩展的结果)

Individual extensions might each produce lift in isolation, but the stack as a whole might not. If Extension A adds +15% and Extension B adds +12% individually, but together they add only +10%, you’re losing value to composition effects. If together they add +20%, you’re getting positive composition: the extensions reinforce each other.单个扩展在孤立时可能都有提升,但整体堆栈未必如此。如果扩展 A 单独贡献 +15%,扩展 B 单独贡献 +12%,但两者一起只贡献 +10%,则组合效应导致价值流失。如果两者一起贡献 +20%,则出现正向组合:扩展相互强化。

A grouped bar chart with four bars. Extension A alone at plus 15 percent, Extension B alone at plus 12 percent, a dashed outline bar showing their expected combined total of plus 27 percent, and a solid bar showing the actual combined result of plus 10 percent. The gap between expected and actual is labeled "composition tax."

Track net lift alongside individual lift to see whether your stack is greater than, equal to, or less than the sum of its parts.同时跟踪净提升和单个提升,以判断您的堆栈是大于、等于还是小于各部分之和。

What actually helps真正有帮助的做法 复制链接

You don’t control other people’s extensions. But you control yours, and you influence how your users configure their workspace.您无法控制他人的扩展。但您可以控制自己的扩展,并影响用户如何配置他们的工作空间。

Make your extensions lean让您的扩展保持精简 复制链接

Every token in your tool descriptions and instruction files is a token that could be used for something else. Be concise. If your tool description can convey the same intent in 50 tokens instead of 200, use 50. If your MCP server has 15 tools but only 5 are commonly used, consider splitting it so the harness only loads what’s needed. Similarly, if you provide a set of skills, that are commonly used together, bundle them into a single skill with progressive disclosure and routing instead of separate skills that each take up context.工具描述和指令文件中的每个 token 都是本可以用于其他用途的 token。保持简洁。如果您的工具描述可以用 50 个 token 表达相同意图,而不是 200 个,请使用 50 个。如果您的 MCP 服务器有 15 个工具,但只有 5 个常用,考虑拆分,使系统只加载必要的部分。同理,如果您提供一组常一起使用的技能,最好将它们打包成一个具备渐进展示和路由的单一技能,而不是每个技能都占用上下文。

You’d think more detail means better tool selection. It doesn’t. In a crowded context window, brevity wins. A short, precise description that actually fits in the context is infinitely better than a detailed one that gets truncated.您可能会认为更详细就能更好地选择工具。事实并非如此。在拥挤的上下文窗口中,简洁才是王道。一个短小、精准且能完整放入上下文的描述,远胜于被截断的冗长描述。

Use distinct vocabulary使用独特的词汇 复制链接

If your tool does something that other tools also do, find language that’s specific to your technology. Instead of “manage authentication settings” (which could match 10 different tools), use your product name and specific terminology: “configure Contoso Identity PKCE flow.” The model can still match it to the intent “set up auth,” but now it has a distinguishing signal when another auth tool is present.如果您的工具做的事情其他工具也能做,请使用特定于您技术的语言。不要使用“管理身份验证设置”(可能匹配 10 种工具),而是使用您的产品名称和专有术语,例如“配置 Contoso Identity PKCE 流”。模型仍然可以将其匹配到“设置身份验证”的意图,但在另一个身份验证工具出现时,它会有区分信号。

Test in realistic environments在真实环境中测试 复制链接

Don’t evaluate your extension in isolation only. Build profiles that include the extensions your audience actually uses. If your developers typically have an Azure extension, a Docker extension, and a testing framework extension installed, test with those present. Your extension needs to produce lift in that environment, not in a clean room.不要只在孤立环境中评估您的扩展。构建包含目标受众实际使用的扩展的配置文件。如果您的开发者通常同时装有 Azure 扩展、Docker 扩展和测试框架扩展,请在这些扩展存在的情况下进行测试。您的扩展需要在这种环境中产生提升,而不是在干净的实验室里。

Document known conflicts记录已知冲突 复制链接

If your extension conflicts with popular tools, say so. If it works best as the only extension for a particular domain, say that too. Developers can’t fix composition problems they don’t know about.如果您的扩展与流行工具冲突,请说明。如果它在特定领域作为唯一扩展时效果最佳,也请注明。开发者无法解决他们不知道的组合问题。

Keep measuring持续测量 复制链接

Composition is a moving target. Other extensions update their descriptions. Harnesses change how they rank tools. New extensions appear. An extension stack that works today might develop composition problems next month. Include composition testing in your regular evaluation cycle, not as a one-time check.组合是一个动态目标。其他扩展会更新它们的描述,系统会改变工具排序,新扩展会不断出现。今天可行的扩展堆栈,可能在下个月出现组合问题。请将组合测试纳入常规评估周期,而不是一次性检查。

Summary总结 复制链接

Extensions don’t exist alone. They share a finite context window and compete for the model’s attention, often interfering in ways invisible from the outside. More extensions don’t mean better outcomes. Past a threshold, each one costs more than it contributes.扩展并非独立存在。它们共享有限的上下文窗口并争夺模型的注意力,常常以外部看不见的方式相互干扰。更多扩展并不等于更好结果。超过阈值后,每个扩展的成本会超过其贡献。

Measure net lift across your full stack, not just individual extension impact. Keep your extensions lean enough to compose well with whatever else is installed. In the next article, we’ll look at what happens when the model has never seen your code at all: bootstrapping agent knowledge for proprietary technology with zero pre-training data.衡量整个堆栈的净提升,而不仅仅是单个扩展的影响。让您的扩展保持足够精简,以便能够与其他已安装的扩展良好组合。在下一篇文章中,我们将探讨当模型从未见过您的代码时会发生什么:为专有技术进行零预训练数据的代理知识引导。

Category

Author

Waldek Mastykarz
Principal Developer Advocate

Waldek is a Principal Developer Advocate at Microsoft focusing on AI Coding Agents. He researches AI Coding Agents, and evaluates and improves Agent Experience for Microsoft's products and services.

0 comments