Three weeks ago I watched a coding agent on a teammate’s laptop try to curl an internal metrics endpoint with nothing to do with its task. Nobody asked it to. Not malicious, just a wrong turn while it poked around “understanding the environment” before making a change. We caught it because he happened to have a terminal open next to the agent pane. If he’d been in a meeting, or the agent had been running in the background the way these tools increasingly do, that request goes out and nobody ever knows.

That’s the gap GitHub just started closing. The September 21 weekly Copilot release notes (published September 25, github.blog/changelog) list local sandboxing for agents in public preview, plus an OpenTelemetry integration to pipe agent activity into whatever monitoring stack you already run. Two features, same week, that only make sense together — one restricts what an agent can touch, the other tells you what it touched anyway.

What actually shipped

The changelog entry is terse, which is normal for GitHub’s weekly recaps, but the wording matters:

“Limit agents’ access to files, networks, and credentials with local sandboxing, now in public preview.”

Three categories: files, network, credentials. That’s the boundary. It lives in the Copilot app, meaning agents running locally on a developer’s own machine — not the cloud-hosted agent sessions GitHub already isolates through its own infrastructure. Local agents run with your shell, your permissions, your SSH keys, your cloud CLI tokens sitting in ~/.aws/credentials. Before this, “local” and “sandboxed” were not words you’d put in the same sentence for Copilot’s agent mode. The agent ran as you. Whatever you could reach, it could reach too.

The OTel piece is the other half:

“Track agent activity in your existing monitoring tools with OpenTelemetry, configured through enterprise-managed settings.”

Enterprise-managed configuration, piped into your existing stack — Datadog, Grafana, whatever your team already pays for and already has dashboards and alerts built around. Not a new Copilot-specific observability product you have to bolt onto your workflow and teach your on-call rotation to check.

Two smaller items landed the same week, worth a mention without derailing the point. VS Code now runs agents inside Dev Containers over SSH, Tunnel, and WSL hosts — rolling out gradually — useful if your team develops against a remote box and wants agent execution where the real toolchain lives, not on the thin client. And four models landed across the plan tiers: Claude Opus 5.5 and GPT-6 Sol for Pro+/Max/Business/Enterprise, GPT-6 Luna and Grok 4.7 down to the base Pro tier too. None of that is the story here. The story is the sandbox and the trace.

Should this have shipped a year ago? Yes.

Sandboxing should not be a public preview feature you opt into in late 2026. It should have been default behavior from day one of Copilot executing shell commands without a human confirming each one. The whole pitch of “agent goes off and does things autonomously” rests on unattended execution — you kick off a task and walk away. But unattended execution with full access to your file system, network, and credential store isn’t a feature. It’s a liability wearing a feature’s clothes. Shipping this as opt-in preview rather than default-on tells you the industry built the capability first and is now, a full product cycle later, building the seatbelt.

That ordering wasn’t reckless, exactly. Sandboxing local processes well, without breaking legitimate workflows that need occasional network or file access outside a narrow project directory, is a genuinely hard problem. Docker took years to get container escapes down to rare CVEs instead of a Tuesday. But hard doesn’t mean it should have waited. A default-deny sandbox with an easy per-project allowlist would have been the safer starting point even in imperfect early form.

Is OpenTelemetry the right abstraction for agent observability?

“Route it through OTel” sounds like the obviously correct engineering answer, and I don’t think it fully is.

OTel is good at what it was built for: distributed tracing across services, with a mature ecosystem of collectors, exporters, and dashboards most platform teams already run. Reusing that pipe for agent activity is the pragmatic choice — nobody wants a fourth observability vendor dashboard next to the three they already have. For the plumbing layer, OTel is the right call.

But an HTTP span and “the agent wrote to this file because it inferred X and got approval via mechanism Y” are different shapes of information wearing the same wire format. Distributed tracing answers “where did the latency go” and “which service threw the error.” Agent observability needs to answer why the agent believed an action was authorized, what sandbox boundary applied at the moment it acted, and whether a human was actually in the loop or it self-approved against a stale policy. OTel’s span/attribute model can carry that if you’re disciplined about the attributes. It does nothing to force that discipline. Nothing in the wire format tells you whether your traces would hold up in a security postmortem or are just latency graphs with an agent name slapped on. That’s a schema problem GitHub hasn’t published an answer to, at least not in this changelog.

What a useful agent-action span should look like

If I were instrumenting this, here’s roughly the shape I’d want per agent action — not “a tool was called” but enough to reconstruct the decision later:

{
  "trace_id": "a1b2c3d4e5f6",
  "span_id": "7f8e9d0c1b2a",
  "name": "agent.tool_call.file_write",
  "start_time": "2026-09-26T03:14:22.104Z",
  "end_time": "2026-09-26T03:14:22.311Z",
  "attributes": {
    "agent.session_id": "copilot-local-9f21",
    "agent.model": "gpt-6-luna",
    "agent.task_description_hash": "sha256:7c4a...",
    "sandbox.boundary_id": "project-scoped-default",
    "sandbox.fs_scope": ["/home/dev/repo/**"],
    "sandbox.network_policy": "deny-all",
    "sandbox.credential_scope": "none",
    "action.type": "file_write",
    "action.target_path": "/home/dev/repo/src/config.ts",
    "action.bytes_written": 842,
    "action.within_sandbox_boundary": true,
    "approval.required": false,
    "approval.granted_by": null,
    "approval.mechanism": "auto-allowed-in-scope",
    "outcome.status": "success",
    "outcome.diff_ref": "git:working-tree:src/config.ts"
  }
}

And a blocked network attempt — arguably the more important record six months later when someone asks “did this thing ever try to reach outside the box”:

{
  "name": "agent.tool_call.network_request",
  "attributes": {
    "agent.session_id": "copilot-local-9f21",
    "sandbox.network_policy": "deny-all",
    "action.type": "network_request",
    "action.target_host": "internal-metrics.corp.example.com",
    "action.method": "GET",
    "action.within_sandbox_boundary": false,
    "outcome.status": "blocked_by_sandbox",
    "outcome.reason": "network_policy_deny_all"
  }
}

The fields doing the actual work aren’t the generic OTel ones — trace_id, start_time, standard stuff. It’s sandbox.boundary_id, sandbox.network_policy, action.within_sandbox_boundary, and approval.granted_by. Those tell a reviewer, after the fact, exactly which rule set was active, whether the action stayed inside it, and whether a human signed off or the system auto-approved. Strip those out and you’re left with a trace that proves an agent did something, with no way to tell whether it was supposed to.

GitHub hasn’t published an actual span schema as far as I can find, and that’s what I’d want next, not more headline features. A tracing pipe without a documented, opinionated schema for “agent authorization context” just becomes another place raw logs pile up, unread, until an incident forces someone to dig through them.

What to verify before you trust this on your own team

Don’t take “sandboxing shipped” and “OTel integration shipped” as settled. Check these before rolling out past a pilot group:

  • Default policy, not just the feature flag. Confirm what the sandbox denies out of the box — file scope, network reachability, credential access — before any project config is layered on. “Public preview” doesn’t mean “safe defaults.”
  • Escape hatches and how they’re logged. Every sandbox needs legitimate ways to grant broader access for a specific task. Find out how that grant happens, whether it needs explicit human approval, and whether the grant itself shows up in the trace.
  • What “credential access” excludes. Blocking reads of ~/.aws/credentials is different from blocking an agent from inheriting a live SSH agent socket or a cached cloud CLI token. The changelog wording doesn’t distinguish these.
  • Whether blocked actions get traced, not just successful ones. A blocked network call is the more security-relevant event. If your OTel pipeline only carries completed actions, you’re missing the interesting half.
  • Who owns the OTel schema on your side. Don’t let this land as raw spans in Datadog nobody queries. Assign someone to define “suspicious agent trace” and build the alert before an incident forces it.
  • Test the boundary yourself. Don’t trust the preview label. Point a sandboxed agent at a task that would naturally want a credential file or an internal host, and confirm it actually gets stopped.

Sandboxing and tracing are both necessary. Neither one is sufficient by itself, and neither one is finished just because it shipped.

Export for reading

Comments