Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions development/examples/private-diy-stack/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.PHONY: run ui record

run:
@bash ./run.sh

ui:
@python3 ./dashboard.py

record:
@bash ./record.sh
31 changes: 31 additions & 0 deletions development/examples/private-diy-stack/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Private DIY Enterprise Stack — Safely On-Premises & in Cloud (`Gemma / DeepSeek` + `Agent Harness` + `Agent Mesh`)

Run a zero-trust AI workforce **safely across on-premises infrastructure and Google Cloud** (Cloud Run, GKE, or local servers) without site-to-site VPNs, inbound firewall holes, or raw credentials inside agent containers:

1. **The "Sidecar" Node Architecture Across On-Prem & Cloud:**
- [`node-agent.yaml`](./node-agent.yaml) runs alongside your agent ([`agent_harness.py`](./agent_harness.py), whether on a workstation, Cloud Run, or GKE) and exposes the mesh as a local **Model Context Protocol (MCP)** server (`127.0.0.1:19101/mcp`) and a local **OpenAI-compatible endpoint** (`127.0.0.1:19101/v1`). The agent has zero database credentials or network routing code.
- [`node-inference.yaml`](./node-inference.yaml) sits next to your GPU reasoning server (`Ollama` / `vLLM` serving `deepseek-r1:1.5b` or `gemma3` in cloud or on-prem) and publishes `inference://private-llm` to the mesh.
- [`node-tools.yaml`](./node-tools.yaml) sits inside the on-premises vault zone next to your private SQLite ERP database (`mcp://erp-db`), Payroll vault (`mcp://payroll-vault`), and internal Vendor Compliance REST API (`egress://compliance.internal`), injecting the Vault-brokered API secret (`secrets/compliance-api-key`) at the egress boundary so sensitive credentials never leave the vault node.

2. **Zero-Trust Identity & Default-Deny Policy ([`policy.json`](./policy.json)):**
- **Default-Deny on Service Names:** Even though `mcp://payroll-vault` runs on the same vault node as `mcp://erp-db`, the control plane policy only grants `mcp://erp-db`—calls to `mcp://payroll-vault` are cryptographically rejected.
- **HTTP Method/Path Guardrails:** `egress://compliance.internal` permits `GET /v1/vendors/*` and blocks `POST` mutations with `HTTP 403`.
- **Residency & Department Labels:** `node-tools.yaml` enforces `check if label("residency", "on-prem");` and `check if label("dept", "finance");`.
- **Task-Scoped Sealed Biscuits (`tar_block`):** Minting a task token via RFC 8693 `/oauth/token` narrows the agent's Biscuit to `lookup_invoice` and `check_inventory`, blocking prompt-injected calls to `execute_wire_transfer`.

## Quick Start

```bash
# 1. Run the 4-act CLI verification script (~12s, zero external dependencies)
make -C development/examples/private-diy-stack run

# 2. Launch the Interactive Browser Workbench on http://127.0.0.1:18899
make -C development/examples/private-diy-stack ui

# 3. Or connect inference://private-llm to a live Ollama / vLLM server:
USE_LIVE_OLLAMA=1 OLLAMA_MODEL=deepseek-r1:1.5b \
make -C development/examples/private-diy-stack ui

# 4. Re-record the 3-pane terminal MP4 walkthrough (see SCRIPT.md):
make -C development/examples/private-diy-stack record
```
30 changes: 30 additions & 0 deletions development/examples/private-diy-stack/SCRIPT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Private DIY Enterprise Stack (On-Prem & Cloud) — 3D Live-Execution Video Script

[`record.sh`](./record.sh) and [`render_3d_video.py`](./render_3d_video.py) produce a 56-second, 1920x1080 (30fps) **3D perspective architectural walkthrough** (`site/static/demo-private-diy-stack.mp4`) driven by a **real live execution** of `agentmesh-one`, four `agentmesh-node` sidecars, `agent_harness.py`, `mcp-client`, and `backends.py`.

## How It Works

1. **Step 1 — Boot Real Mesh Binaries (`MeshEnvironment`):**
- Starts `backends.py` (SQLite ERP database `mcp://erp-db`, Payroll Vault `mcp://payroll-vault`, Vendor Compliance REST API `egress://compliance.internal`, and OpenAI-compatible reasoning engine `inference://private-llm`).
- Starts `agentmesh-one` with [`policy.json`](./policy.json) and enrolls four real `agentmesh-node` sidecars:
- [`node-agent.yaml`](./node-agent.yaml) (`127.0.0.1:19101` — Cloud Run / Workstation zone)
- [`node-inference.yaml`](./node-inference.yaml) (`127.0.0.1:19103` — Cloud / On-Prem GPU zone)
- [`node-tools.yaml`](./node-tools.yaml) (`127.0.0.1:19102` — On-Premises Corporate Vault zone)
- [`node-external.yaml`](./node-external.yaml) (`127.0.0.1:19104` — Untrusted External zone, `dept=external`)

2. **Step 2 — Execute All 4 Acts Against Live Binaries:**
- **Scene 1 (Act 1 — Sidecar Discovery):** Queries `/api/act1/discover` to verify real libp2p Peer IDs (`12D3KooW...`) and Kademlia DHT service discovery.
- **Scenes 2 & 3 (Act 2 — Hybrid ReAct Loop & Vault Secret Brokering):** Executes `agent_harness.py` via `/api/act2/run-agent` to audit `INV-2026-089`, check `SKU-GPU-H200` stock, and verify vendor `ACME-01` with node-side `secrets/compliance-api-key` injection.
- **Scene 4 (Act 3a & 3b — Default-Deny on Service Names & HTTP Methods):** Calls `mcp://payroll-vault/dump_executive_salaries` and `POST /v1/vendors/ACME-01`, capturing the live Biscuit Datalog denial and `HTTP 403` response.
- **Scene 5 (Act 3c — Residency & Department Label Check):** Calls `mcp://erp-db/lookup_invoice` from `node-external` (`dept=external`), capturing the live Datalog label rejection on `node-tools`.
- **Scene 6 (Act 3d — Task-Scoped Sealed `tar_block` Biscuit):** Mints a task-scoped sealed Biscuit via RFC 8693 `POST /oauth/token`, verifies `lookup_invoice` (`ALLOW`), and blocks prompt-injected `execute_wire_transfer` (`DENY`).
- **Scene 7 (Act 4 — Correlated Audit Trail & Mesh-Wide Ban):** Revokes `node-external` via `agentmesh-one admin ban` and summarizes all live `ALLOW` / `DENY` audit events.

3. **Step 3 — 3D Perspective Rendering (`pycairo` + `numpy` + `ffmpeg`):**
- Renders the 3D zones, extruded server racks, rotating Biscuit holocubes, curved 3D `libp2p` packet beams, 3D hexagonal force-field shields on `DENY`, and the live binary telemetry HUD to `site/static/demo-private-diy-stack.mp4`.

## Re-Recording

```bash
make -C development/examples/private-diy-stack record
```
224 changes: 224 additions & 0 deletions development/examples/private-diy-stack/agent_harness.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
#!/usr/bin/env python3
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Self-Hosted Agent Harness (ReAct Loop) talking ONLY to its local agentmesh-node sidecar.

Notice what is NOT in this file:
- No database URLs, SQLite paths, or SQL credentials
- No corporate IP addresses or VPN routes
- No upstream API keys for compliance.internal
- No LLM server addresses

The harness talks strictly to its local sidecar (http://127.0.0.1:19101):
- /mcp for discovering and calling tools across the mesh
- /v1 for calling the self-hosted DeepSeek/Gemma reasoning model
- /mesh/<peer>/egress/compliance.internal/... for reaching internal REST APIs with brokered secrets
"""

import json
import os
import sys
import urllib.request

SIDECAR_URL = os.environ.get("AGENTMESH_SIDECAR_URL", "http://127.0.0.1:19101").rstrip("/")
API_TOKEN = os.environ.get("AGENTMESH_API_TOKEN", "agent-sidecar-secret")
LLM_MODEL = os.environ.get("LLM_MODEL", "deepseek-r1:1.5b")


class LocalSidecarClient:
"""Minimal stdlib client for the local agentmesh-node sidecar (/mcp, /v1, /mesh)."""

def __init__(self, base_url: str, token: str) -> None:
self.base_url = base_url
self.token = token
self.session_id: str | None = None
self._req_id = 0
self._opener = urllib.request.build_opener(urllib.request.ProxyHandler({}))

def _next_id(self) -> int:
self._req_id += 1
return self._req_id

def mcp_rpc(self, method: str, params: dict | None = None) -> dict:
headers = {
"Content-Type": "application/json",
"Accept": "application/json, text/event-stream",
"X-Mesh-Authentication": f"Bearer {self.token}",
}
if self.session_id:
headers["Mcp-Session-Id"] = self.session_id

payload: dict = {"jsonrpc": "2.0", "method": method}
if not method.startswith("notifications/"):
payload["id"] = self._next_id()
if params is not None:
payload["params"] = params

req = urllib.request.Request(
f"{self.base_url}/mcp",
data=json.dumps(payload).encode("utf-8"),
headers=headers,
method="POST",
)
with self._opener.open(req, timeout=15) as resp:
sid = resp.headers.get("Mcp-Session-Id")
if sid:
self.session_id = sid
raw = resp.read().decode("utf-8").strip()
if not raw:
return {}
# Streamable HTTP may return plain JSON or SSE "data: {...}" lines
for line in reversed(raw.splitlines()):
line = line.strip()
if line.startswith("data:"):
line = line[len("data:") :].strip()
if line.startswith("{"):
return json.loads(line)
return json.loads(raw)

def init_mcp(self) -> None:
self.mcp_rpc(
"initialize",
{
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "private-diy-harness", "version": "1.0.0"},
},
)
self.mcp_rpc("notifications/initialized")

def call_sidecar_tool(self, name: str, arguments: dict) -> str:
res = self.mcp_rpc("tools/call", {"name": name, "arguments": arguments})
if "error" in res:
raise RuntimeError(json.dumps(res["error"]))
result = res.get("result") or {}
texts = [c.get("text", "") for c in (result.get("content") or []) if c.get("type") == "text"]
text_out = "\n".join(texts).strip()
if result.get("isError"):
raise RuntimeError(text_out)
return text_out

def chat_completion(self, messages: list[dict]) -> str:
req = urllib.request.Request(
f"{self.base_url}/v1/chat/completions",
data=json.dumps({"model": LLM_MODEL, "messages": messages, "stream": False}).encode("utf-8"),
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {self.token}",
},
method="POST",
)
with self._opener.open(req, timeout=30) as resp:
body = json.loads(resp.read().decode("utf-8"))
return body["choices"][0]["message"]["content"]

def call_egress_get(self, peer_id: str, destination: str, path: str) -> dict:
req = urllib.request.Request(
f"{self.base_url}/mesh/{peer_id}/egress/{destination}{path}",
headers={"X-Mesh-Authentication": f"Bearer {self.token}"},
method="GET",
)
with self._opener.open(req, timeout=15) as resp:
return json.loads(resp.read().decode("utf-8"))


def main() -> None:
task_prompt = (
sys.argv[1]
if len(sys.argv) > 1
else "Audit Invoice INV-2026-089 for Acme Robotics, verify SKU-GPU-H200 warehouse stock, and check vendor ACME-01 compliance."
)

sidecar = LocalSidecarClient(SIDECAR_URL, API_TOKEN)
sidecar.init_mcp()

print(f' [Harness] Task: "{task_prompt}"')
print(f" [Harness] Step 1 -> Asking local MCP server ({SIDECAR_URL}/mcp) for remote tools on the mesh...")
raw_catalog = sidecar.call_sidecar_tool("find_remote_tools", {"service_name": "erp-db"})
catalog = json.loads(raw_catalog.splitlines()[-1])
tools_found = [entry["tool_name"] for entry in catalog if "tool_name" in entry]
target_peer = catalog[0]["peer_id"]
print(f" Discovered {len(tools_found)} tools on Vault Peer {target_peer[:16]}…: {', '.join(tools_found)}")

schema_raw = sidecar.call_sidecar_tool(
"describe_remote_tool",
{"peer_id": target_peer, "tool_name": "mcp://erp-db/lookup_invoice"},
)
schema_obj = json.loads(schema_raw.splitlines()[-1])
req_fields = schema_obj.get("input_schema", {}).get("required", [])
print(f" Inspected schema for mcp://erp-db/lookup_invoice (required={req_fields})")

print(f" [Harness] Step 2 -> Consulting self-hosted reasoning model ({LLM_MODEL}) via {SIDECAR_URL}/v1/chat/completions...")
plan_response = sidecar.chat_completion(
[
{"role": "system", "content": f"Available mesh tools: {', '.join(tools_found)}"},
{"role": "user", "content": task_prompt},
]
)
for line in plan_response.splitlines():
if line.strip():
print(f" {line}")

print(" [Harness] Step 3 -> Executing tool calls & internal API checks through local sidecar...")
inv_result = sidecar.call_sidecar_tool(
"call_remote_tool",
{
"peer_id": target_peer,
"tool_name": "mcp://erp-db/lookup_invoice",
"arguments": {"invoice_id": "INV-2026-089"},
},
)
print(f" [mcp://erp-db/lookup_invoice] -> {inv_result}")

stock_result = sidecar.call_sidecar_tool(
"call_remote_tool",
{
"peer_id": target_peer,
"tool_name": "mcp://erp-db/check_inventory",
"arguments": {"sku": "SKU-GPU-H200"},
},
)
print(f" [mcp://erp-db/check_inventory] -> {stock_result}")

comp_result = sidecar.call_egress_get(target_peer, "compliance.internal", "/v1/vendors/ACME-01")
print(
f" [egress://compliance.internal] -> vendor={comp_result['name']}, "
f"sanctions={comp_result['sanctions_check']}, iso27001={comp_result['iso27001_certified']} "
f"(brokered secret verified={comp_result['brokered_auth_verified']})"
)

print(f" [Harness] Step 4 -> Sending tool observations back to {LLM_MODEL} for final synthesis...")
final_answer = sidecar.chat_completion(
[
{"role": "user", "content": task_prompt},
{"role": "assistant", "content": plan_response},
{
"role": "user",
"content": (
f"TOOL_OBSERVATIONS:\n"
f"- invoice: {inv_result}\n"
f"- inventory: {stock_result}\n"
f"- compliance: {json.dumps(comp_result)}"
),
},
]
)
for line in final_answer.splitlines():
if line.strip():
print(f" {line}")


if __name__ == "__main__":
main()
43 changes: 43 additions & 0 deletions development/examples/private-diy-stack/audit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env python3
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Reads agentmesh-node logs on stdin and prints one line per authorization or task decision."""

import json
import re
import sys

AUDIT = re.compile(r"Audit Traceability\s+(\{.*\})\s*$")
TAR_DENY = re.compile(r'task authorization denied tool "([^"]+)".*tar_block\[1\] \("([^"]+)"\)')

for raw_line in sys.stdin:
line = raw_line.rstrip("\n")
m = AUDIT.search(line)
if m:
try:
d = json.loads(m.group(1))
except json.JSONDecodeError:
continue
who = f"{d.get('role') or '-'} {d.get('peer_id', '')[:12]}…"
what = " ".join(x for x in (d.get("method"), d.get("path")) if x) or d.get("protocol", "")
print(f"{d.get('decision', '?').upper():<5} {who:<22} {what:<34} {d.get('target', '')}", flush=True)
continue
tm = TAR_DENY.search(line)
if tm:
print(f"DENY tar_block ({tm.group(2)}) tools/call {tm.group(1):<23} mcp://erp-db", flush=True)
continue
if "peer banned" in line:
peer = re.search(r'"peer":\s*"([^"]+)"', line)
print(f"BANNED {peer.group(1) if peer else ''}: control plane revoked peer", flush=True)
Loading
Loading