agent-identity-demos

Cross-domain ID-JAG + VC

A cross-domain agent delegation scenario: Sarah (an engineer at Org A) asks OpenCode (her Org A AI agent) to fix a security weakness in a repo owned by Org B. OpenCode reads the real source through the delegation chain, under its own read-scoped assertion, and reports what it actually finds — a CWE, not a hardcoded CVE. Org B has its own Keycloak realm and access control, so OpenCode can’t act there directly — it asserts Sarah’s delegation cross-domain using ID-JAG (Identity Assertion JWT Authorization Grant), then Triage further delegates a narrowed privilege to a bounded Sub-Agent that actually opens the pull request.

Demo walkthrough

Click the GIF above for the full-quality video.

OpenCode is the real open-source OpenCode agent (opencode.ai, pinned opencode-ai@1.18.7) running headless in the opencode-server container, driven by an identity harness (opencode-agent, port 8100) that executes the task lifecycle Sarah delegates:

OAuth → register own identity (CIMD) → policy-scoped badge → work → delegate cross-domain

Before any task work runs, the harness presents Sarah’s delegated access token to Envoy A + inline OPA (/api/badge-scope-check), which verifies the token against Keycloak A’s JWKS and answers with a scoped-down intent (e.g. scan-remediate:demo-admin/payments-service); only then is the VC badge minted — bound to that one task — and only then does the agent work.

Two AGNTCY components are wired in for real:

The only optional mock is the remediation LLM call itself, toggleable to a fast, clearly-labeled stand-in when a model backend isn’t available.

What’s real vs. mocked

Step(s) What Real or mocked
1 Sarah’s OIDC login at Keycloak A Real
2 Code scan — OpenCode analyses source fetched from the Org B repo Real agent analysis of real source; reports a CWE (falls back to the known fixture finding when no model is reachable)
Read chain: read-scoped ID-JAG mint → Org A egress PDP → Keycloak B redemption → source fetch through Envoy B Real — a second, narrower assertion (gitea:read, repo-bound) minted and enforced end to end
OpenCode remediation plan (headless opencode-server, Ollama/Anthropic) Real agent + LLM call (skipped without a provider)
Badge-scope PDP at Envoy A — verify Sarah’s KC-A token, return task-scoped badge intent Real JWT verification + inline OPA
3–4 AGNTCY Directory push + search (gRPC) Real
5–6 CIMD generate/resolve id + agent badge issued as a W3C Verifiable Credential Real
Every agent publishes its own credential; each side of a handoff resolves the other’s Real
7 RFC 8693 token exchange at Keycloak A Real call
8 ID-JAG mint for Org B triage-agent Real
9–10 Org A egress PDP — may Sarah delegate this scope to Org B? Real
11 Keycloak B jwt-bearer redemption Real
12–13 Envoy ingress, ticket creation, OPA check, plan, sub-badge mint Real
Triage identity lifecycle (in-agent ID-JAG verification, org-b CIMD, native KC-B mint) Real
14–20 Sub-Agent spawn, verification, Gitea push/PR, resource-boundary OPA, audit Real
OpenTelemetry trace_id linking every hop Real

How each piece became real, known limitations of the actor_token check, and reviewer verification steps live in the demo README.

Next