Agentic Sandbox v2026.5.6
Agentic Sandbox v2026.5.6
Released: 2026-05-20 Tag: `v2026.5.6` Previous: `v2026.5.5` (2026-05-20) Compare: `v2026.5.5...v2026.5.6`
What this release is
The A2A routing patch for VM-backed agents. One operator-visible bug fix.
In v2026.5.5 and earlier, agents provisioned via `provision-vm.sh` registered over gRPC and appeared in `/api/v1/agents` — but `/agents/{instance_id}/.well-known/agent-card.json` returned `instance.not_found`. The v2/A2A `InstanceRegistry` was only populated by the admin-v2 provisioning path (`admin_v2.rs`); the gRPC registration path didn't insert anything, so VM-backed agents were invisible to A2A routing.
v2026.5.6 wires the bridge: every gRPC `Registration` now inserts a matching `InstanceContext` into the executor `InstanceRegistry` using the same `instance_id` the v1 listing exposes. AgentCard discovery, the rest of the `/agents/*` surface, and `messages:send` dispatch now work for VM-provisioned agents the same way they work for Docker admin-v2 instances.
What changed since v2026.5.5
- gRPC registration bridges into the v2/A2A `InstanceRegistry` (#317). `AgentServiceImpl` gained optional `instance_registry` + `signing_keys_dir` fields, wired in `main.rs` whenever the executor surface is mounted (always, when `TaskStore` is available). On every `Registration` message:
- The canonical `instance_id` assigned by `ConnectedAgent::new` is read back from the v1 registry.
- A new `bridge_register_instance` helper builds an `InstanceContext` with the per-instance signing key under `<secrets_dir>/instances/<instance_id>/signing.pem` (matches admin-v2 behavior — AgentCard JWS `kid` stays stable across server restarts).
- Empty `loadout` in the Registration message → `RuntimeKind::Container` (legacy `POST /api/v1/containers` path). Non-empty `loadout` → `RuntimeKind::Vm` (cloud-init always materializes a loadout).
- The bridge is idempotent on duplicate `instance_id`: admin-v2's pre-registration is preserved, and the cached AgentCard isn't thrown away when the same agent reconnects.
- Disconnect cleanup. The disconnect path pulls `instance_id` from the v1 registry before unregistering, then removes the matching `InstanceContext`. Order matters — the v1 entry owns the id, so the lookup has to happen first.
- Three regression tests in `management/src/grpc.rs::tests` exercise the bridge directly: `bridge_registers_vm_instance_with_loadout_kind`, `bridge_registers_container_instance_when_loadout_empty`, `bridge_is_idempotent_on_duplicate_instance_id`. Full suite 516 passed locally.
Reproduction the fix addresses
From the agent-ops M011 dual-substrate smoke against v2026.5.5:
$ images/qemu/provision-vm.sh agentops-m011-codex-smoke \
--loadout profiles/codex-only.yaml \
--ssh-key ~/.ssh/vm_ed25519.pub \
--ip 192.168.122.230 \
--management 192.168.122.1:8120 \
--agentshare --network-mode full --wait-ready
# management log:
# Agent registered: agentops-m011-codex-smoke (192.168.122.230)
# /api/v1/agents — visible, instance_id assigned:
$ curl -s http://192.168.122.1:8122/api/v1/agents | jq '.[]'
{
"id": "agentops-m011-codex-smoke",
"instance_id": "019e4392-7e61-7582-8d91-936096a14c8a",
...
}
# A2A AgentCard discovery — 404 instance.not_found:
$ curl -s http://192.168.122.1:8122/agents/019e4392-7e61-7582-8d91-936096a14c8a/.well-known/agent-card.json
{
"type": "instance.not_found",
"title": "Instance not found",
"status": 404,
...
}
After upgrade to v2026.5.6, the same `GET` returns the signed AgentCard with `runtime_kind: "vm"`, the loadout, host, and the instance_id propagated through.
Upgrade matrix
| If you are… | Do this |
|---|---|
| Provisioning VMs via `provision-vm.sh` and consuming A2A | Upgrade — without this fix, AgentCard discovery 404s on VM-backed agents and orchestrators have no `messages:send` routing target. |
| Provisioning via admin-v2 only (Docker or QEMU through `POST /api/v2/admin/instances`) | Upgrade is safe and brings the gRPC bridge for any future direct-gRPC connections, but admin-v2 was already wired correctly — no behavioral change. |
| Running a single-host local sandbox without A2A clients | Upgrade is safe; no behavioral change. |
| Building against the gRPC proto | No proto change — `AgentRegistration.instance_id` semantics unchanged. |
| Running CI in tag context | E2E gate from v2026.5.5 stays in place. |
How to verify the upgrade
git fetch --tags origin
git checkout v2026.5.6
make build
# Versions
./management/target/release/agentic-mgmt --version # 2026.5.6
./cli/target/release/sandboxctl --version # 2026.5.6
./agent-rs/target/release/agent-client --version # 2026.5.6
# Provision and validate A2A resolves
./images/qemu/provision-vm.sh smoke-a2a \
--loadout profiles/agentic-dev.yaml \
--ssh-key ~/.ssh/vm_ed25519.pub \
--wait-ready
INSTANCE_ID=$(curl -s http://127.0.0.1:8122/api/v1/agents \
| jq -r '.[] | select(.id=="smoke-a2a") | .instance_id')
curl -s -o /dev/null -w "%{http_code}\
" \
"http://127.0.0.1:8122/agents/${INSTANCE_ID}/.well-known/agent-card.json"
# Expect: 200
./scripts/destroy-vm.sh --force smoke-a2a
Issues closed
- #317 — VM-provisioned agents register in v1 registry but are not routable A2A instances.
Known limitations / deferred
Carried forward from v2026.5.5, unchanged:
- #917 identity-across-reconnects (a Registration with a re-used `instance_id` is reused; a Registration with an empty `instance_id` synthesizes a fresh one per connection). The bridge follows the v1 registry's lead, so the longer-term identity story isn't blocked by this fix.
- #256 / #257 WS bearer-auth-on-upgrade and full TLS wiring stay open.
- #114 + children (Alpine + Proxmox provisioning) deferred to 2026-08-17 check date.
Full change log
See [`CHANGELOG.md` `[2026.5.6]`](../../CHANGELOG.md#202656-2026-05-20) for the Fixed / Documentation / Operator-notes / Issues-closed breakdown.
Tagging procedure
git tag -a v2026.5.6 -m "$(cat <<'EOF'
v2026.5.6 — A2A routing patch for VM-backed agents
One operator-visible bug fix. VM-provisioned agents register over gRPC and
appear in /api/v1/agents but /agents/{instance_id}/.well-known/agent-card.json
returned 404 instance.not_found because the v2/A2A InstanceRegistry was only
populated by the admin-v2 provision path. The gRPC Registration handler now
bridges every connecting agent into the executor InstanceRegistry using the
same instance_id the v1 listing exposes; idempotent on duplicates so admin-v2
pre-registration survives, with matching disconnect cleanup. Three regression
tests cover VM kind, Container fallback, and idempotency.
Closes #317.
Full notes: docs/releases/v2026.5.6.md and CHANGELOG.md [2026.5.6]
EOF
)"
git push origin v2026.5.6
git push github v2026.5.6