Repository navigation
Squad telemetry from embedded host processes (Agent Framework wrappers, no REPL): how should it reach Aspire? #1144
Description
Summary
Today, squad aspire shows beautiful telemetry — agent spawns, token consumption, session metrics, errors — but only when the work happens through the Squad CLI (squad run, squad watch, the REPL, etc.). When Squad is wrapped as an Agent Framework agent in a host process (a SquadAgent : AIAgent class in C# that calls CopilotClient from GitHub.Copilot.SDK directly), nothing shows up in the Aspire dashboard.
The instrumentation lives in the Node.js Squad SDK (packages/squad-sdk/src/runtime/otel-*.ts — otel-init.ts, otel-metrics.ts, otel-bridge.ts, otel-api.ts). When a C#/Python/Java host invokes the Copilot SDK directly, the Squad CLI runtime is not in the call path, so the OTel emitter never fires.
Concrete scenario
I'm building tamirdresher_microsoft/squad-agent-framework-demo — a .NET Aspire app that orchestrates a durable incident-response workflow with Squad agents as Microsoft Agent Framework participants. The architecture looks like:
Aspire AppHost
├─ Foundry Local (chat model)
├─ DTS emulator container
└─ Demo console
├─ MAF Workflow (TriageExecutor → EnrichExecutor → ...)
│ emits OTel via Microsoft.Agents.AI.Workflows ✅
└─ SquadAgent.cs (wraps CopilotClient from GitHub.Copilot.SDK)
emits OTel ❌ ← the gap
The user can run squad aspire separately, but it shows nothing — the SquadAgent.cs path bypasses the Node runtime entirely. Two Aspire dashboards, none of them see the C# wrapper's runtime activity.
(I'm working around this for now by adding a C# ActivitySource("Squad.AgentFramework.SquadAgent") directly inside the wrapper class, but that schema is mine — it won't match what squad aspire displays for native CLI sessions, and it won't be portable to other language wrappers.)
What I'd love to discuss
How should Squad telemetry flow when Squad is embedded as a host-process agent (no REPL, no CLI runtime)?
A few options I see:
-
Publish a Squad Telemetry Contract — document the ActivitySource names, span attributes, metric names, and the OTel resource attributes the Squad CLI emits. Any language wrapper can adopt the same schema and the Aspire dashboard's filters/views "just work". (Low effort upstream, leaves wrappers to DIY.)
-
Ship a small per-language telemetry helper — a
Squad.TelemetryNuGet package (and pip equivalent, etc.) that exposesStartAgentRun,RecordToolCall,RecordSessionEventmethods backed by the contract above. Wrappers call into it; OTel registration stays user-controlled. (Medium effort upstream, very low effort for wrappers.) -
Make the Copilot SDK itself OTel-aware — push the instrumentation down a layer so
CopilotClient(and equivalents) emit the same spans regardless of who calls them. Squad CLI keeps its existing higher-level instrumentation; wrappers get session/agent-level traces for free. (Higher effort, touches the Copilot SDK team — not in your sole control.) -
Side-channel: a long-lived
squad telemetryprocess that wrappers post events to over a local socket / HTTP, which then re-emits via the Node OTel pipeline. Keeps a single source of truth for emission. (Higher complexity, latency tax on every span.)
Option 1 (the schema doc) plus Option 2 (a thin C# helper) feels like the cleanest 80/20.
Why this matters
The Squad value prop is more interesting once Squad participates in larger orchestrations — durable workflows, multi-agent compositions, cross-service incident responses. In those contexts, the operator wants ONE dashboard that shows the workflow spans AND the Squad agent reasoning AND the deterministic activities in between. Today they can have any two of those three; not all three. Closing this gap unlocks ""Squad as a first-class observable participant in any host you want"".
Happy to PR Option 1 (the contract doc) myself if it would help. Let me know what direction makes sense.
— Tamir
Activity
laurentkempe commentedon May 20, 2026
Hi @tamirdresher
It is already the case: https://github.com/github/copilot-sdk/blob/main/docs%2Fobservability%2Fopentelemetry.md
Can't access your repo, btw
tamirdresher commentedon May 20, 2026
Thanks @laurentkempe I will the repo to my public github.
What is missing is the squad metrics themselves. Maybe this will be provided out of the box from the copilot sdk, I need to check
Thanks for the pointer :-)
tamirdresher commentedon May 20, 2026
Thanks @laurentkempe — you're right, and I owe you a clearer framing. I missed the observability doc, which already answers most of what I asked about Option 3.
TelemetryConfig.OtlpEndpoint, GenAI + MCP semantic conventions, automatic trace-context propagation across the JSON-RPC boundary — all already there. Sorry for the noise on that point.So the actual gap is narrower than my original post described. Let me restate it:
TelemetryConfig(your point). 👍Microsoft.Agents.AI.GitHub.Copilot.GitHubCopilotAgent) → wraps aCopilotClient. The remaining question is whether the wrapper exposes a way to surface thatTelemetryConfigto consumers. If yes — the host process just needs to subscribe to the SDK'sActivitySourcein itsTracerProvider. I'm checking the wrapper's public surface today; will report back. (If you've already looked, I'd love a pointer.)packages/squad-sdk/src/runtime/otel-*.tsemits agent-spawn / casting / coordinator-routing spans on top of whatever the Copilot SDK does. That layer is genuinely Squad-specific — agent spawned, agent retired, casting decision, routing change, ralph round, etc. Those aren't in the GenAI/MCP conventions because they're Squad's domain model.So my refined ask is really about (3): does it make sense to publish a "Squad telemetry semantic convention" — span names, attribute keys, metric names — that any wrapper (C#, Python, future Java) can adopt, layered on top of GenAI/MCP? That way
squad aspireand any embedded host can each emit the same Squad-specific events using the same names, and the Aspire dashboard filters/views work uniformly across them. It's a smaller document than I implied — basically a "here's what Squad emits beyond the Copilot SDK and why" reference.Re access — apologies, my demo repo is in a Microsoft EMU org and I forgot it'd be private to outside viewers. I'll either mirror it to my personal account or paste the relevant 40 lines from
SquadAgent.csandProgram.csinline in a follow-up comment so you can see what I'm actually doing. Will follow up shortly.— Tamir
laurentkempe commentedon May 20, 2026
Nice @tamirdresher I am also interested about the MAF/Copilot SDK/Squad integration as I am working on something similar at the moment.
I think so
tamirdresher commentedon May 20, 2026
Quick follow-up — the demo repo is now public and accessible:
🔗 https://github.com/tamirdresher/squad-agent-framework-demo
MIT-licensed, single-commit squash of our internal PRs #1-8 (and #9, which is landing as I type this — a tiny TLS fix described below). The README links back to the companion blog post.
Relevant to your earlier point about the Copilot SDK already having OTel:
You were absolutely right —
CopilotClientOptions.Telemetry = new TelemetryConfig { OtlpEndpoint = ... }is the canonical path, and we're now wiring it directly. The interesting bits if you want to skim:SquadAgent.cs—EnsureInnerAsyncreadsOTEL_EXPORTER_OTLP_ENDPOINTand passes it through toCopilotClientviaTelemetryConfig. The MAF wrapper (Microsoft.Agents.AI.GitHub.Copilot.GitHubCopilotAgent) takes a pre-builtCopilotClient, so no upstream change was needed there.AppHost.cs— Aspire auto-injects the OTLP endpoint env var, so the CLI's exporter just picks it up.Program.cs— registers the .NET-sideActivitySources (Squad.AgentFramework.Demofor workflow stages,Squad.AgentFramework.SquadAgentfor the agent wrapper). The Copilot CLI exports its own spans as a separate service and they get linked to the .NET parent activity via W3C trace-context propagation — exactly as the SDK doc describes.One real-world wrinkle worth flagging if it helps anyone else: in Aspire's local dev mode the OTLP endpoint uses a self-signed cert, and Node.js rejects it with
NODE_TLS_REJECT_UNAUTHORIZED=1(default). The single-line fix is.WithEnvironment("NODE_TLS_REJECT_UNAUTHORIZED", "0")on the demo resource — that's PR #9, going live now. After that the CLI spans actually show up in the dashboard alongside the .NET ones.On the Squad-specific gap I mentioned: still standing, but narrower than I framed it. The Copilot SDK + GenAI/MCP conventions cover the agent's per-turn telemetry beautifully. What's not covered are the coordinator-level events — agent-spawn, casting decisions, work-routing, reviewer gates — which live in the Squad CLI's Node-side runtime (
packages/squad-sdk/src/runtime/otel-*.ts) and don't map cleanly to existing conventions. Happy to keep that conversation in #1144 or split it into something more focused — your call.Thanks again for the redirect — saved us from shipping a much wordier ask.
feat: add CommunityToolkit.Aspire.Hosting.Squad
feat: add CommunityToolkit.Aspire.Hosting.Squad - first-class Aspire …
bradygaster commentedon Aug 3, 2026
Companion docs issue filed: #1565 (
docs: Squad.Agents.AI + Microsoft Agent Framework integration guide). That issue will document the user-facing integration guide — including the telemetry story (squad.subagent {Name}OTel spans, Aspire dashboard wiring) — once the telemetry mechanism tracked here is settled. The two should move together; please cross-link when #1144 has a resolution. See umbrella #1564 for full context.bradygaster commentedon Sep 23, 2026
Closing as resolved — PR #1265 added first-class OpenTelemetry support for
Squad.Agents.AI(src/Squad.Agents.AI/SquadAgentDiagnostics.csdefinesActivitySourceName), with Aspire/OTel wiring documented insrc/Squad.Agents.AI/README.md:169-185.