Skip to content

Squad telemetry from embedded host processes (Agent Framework wrappers, no REPL): how should it reach Aspire? #1144

Closed

Description

@tamirdresher

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:

  1. 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.)

  2. Ship a small per-language telemetry helper — a Squad.Telemetry NuGet package (and pip equivalent, etc.) that exposes StartAgentRun, RecordToolCall, RecordSessionEvent methods backed by the contract above. Wrappers call into it; OTel registration stays user-controlled. (Medium effort upstream, very low effort for wrappers.)

  3. 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.)

  4. Side-channel: a long-lived squad telemetry process 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

  1. laurentkempe commented on May 20, 2026

    @laurentkempe

    Hi @tamirdresher

    Make the Copilot SDK itself OTel-aware

    It is already the case: https://github.com/github/copilot-sdk/blob/main/docs%2Fobservability%2Fopentelemetry.md

    Can't access your repo, btw

  2. tamirdresher commented on May 20, 2026

    @tamirdresher
    CollaboratorAuthor

    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 :-)

  3. tamirdresher commented on May 20, 2026

    @tamirdresher
    CollaboratorAuthor

    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:

    1. Copilot SDK OTel → already emits via TelemetryConfig (your point). 👍
    2. C# Agent Framework wrapper (Microsoft.Agents.AI.GitHub.Copilot.GitHubCopilotAgent) → wraps a CopilotClient. The remaining question is whether the wrapper exposes a way to surface that TelemetryConfig to consumers. If yes — the host process just needs to subscribe to the SDK's ActivitySource in its TracerProvider. I'm checking the wrapper's public surface today; will report back. (If you've already looked, I'd love a pointer.)
    3. Squad CLI's own telemetry → the Node-side instrumentation in packages/squad-sdk/src/runtime/otel-*.ts emits 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 aspire and 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.cs and Program.cs inline in a follow-up comment so you can see what I'm actually doing. Will follow up shortly.

    — Tamir

  4. laurentkempe commented on May 20, 2026

    @laurentkempe

    Nice @tamirdresher I am also interested about the MAF/Copilot SDK/Squad integration as I am working on something similar at the moment.

    it make sense to publish a "Squad telemetry semantic convention"

    I think so

  5. tamirdresher commented on May 20, 2026

    @tamirdresher
    CollaboratorAuthor

    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 — EnsureInnerAsync reads OTEL_EXPORTER_OTLP_ENDPOINT and passes it through to CopilotClient via TelemetryConfig. The MAF wrapper (Microsoft.Agents.AI.GitHub.Copilot.GitHubCopilotAgent) takes a pre-built CopilotClient, 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-side ActivitySources (Squad.AgentFramework.Demo for workflow stages, Squad.AgentFramework.SquadAgent for 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.

  6. bradygaster commented on Aug 3, 2026

    @bradygaster
    Owner

    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.

  7. bradygaster commented on Sep 23, 2026

    @bradygaster
    Owner

    Closing as resolved — PR #1265 added first-class OpenTelemetry support for Squad.Agents.AI (src/Squad.Agents.AI/SquadAgentDiagnostics.cs defines ActivitySourceName), with Aspire/OTel wiring documented in src/Squad.Agents.AI/README.md:169-185.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    triagedIssue has been triagedwave:2-soonWave 2 — next 2-4 weeks

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions