From 9bd66720a7c74999f42df72977254e538fc2aad4 Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Fri, 20 Mar 2026 10:56:05 -0700 Subject: [PATCH 01/12] docs: add testing guide for external testers and customers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/TESTING_GUIDE.md | 308 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 docs/TESTING_GUIDE.md diff --git a/docs/TESTING_GUIDE.md b/docs/TESTING_GUIDE.md new file mode 100644 index 00000000..7c37312d --- /dev/null +++ b/docs/TESTING_GUIDE.md @@ -0,0 +1,308 @@ +# Testing Guide — How to Use the Agent Governance Toolkit + +> This guide walks you through using the Agent Governance Toolkit as an external +> customer would, from zero to a fully governed AI agent. No prior knowledge required. + +## What Is This Toolkit? + +The Agent Governance Toolkit is **not** a portal or a UI. It's a **Python library** that sits +between your AI agent and the tools it uses (APIs, databases, files). Think of it as a +security middleware — every action your agent tries to take gets checked against your +policies before it's allowed to execute. + +``` +Your Agent → [Governance Toolkit] → Tool/API/Database + ↓ + Policy check: ALLOW or DENY + Audit log: who did what, when +``` + +## Prerequisites + +- Python 3.10+ installed +- An API key for any LLM provider (OpenAI, Azure OpenAI, or Google Gemini) +- 10 minutes + +--- + +## Path 1: Run the Live Demo (Fastest — 5 minutes) + +This is the best way to see what the toolkit does. The demo runs 4 governance +scenarios with a real LLM and shows you policy enforcement in action. + +### Step 1: Clone and install + +```bash +git clone https://github.com/microsoft/agent-governance-toolkit.git +cd agent-governance-toolkit +pip install -e "packages/agent-os[dev]" +pip install -e "packages/agent-mesh" +pip install -e "packages/agent-compliance" +pip install httpx pyyaml +``` + +### Step 2: Set your LLM API key + +Pick ONE of these (the demo auto-detects which one you have): + +```bash +# Option A: OpenAI +export OPENAI_API_KEY="sk-..." + +# Option B: Azure OpenAI +export AZURE_OPENAI_API_KEY="..." +export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com" + +# Option C: Google Gemini +export GOOGLE_API_KEY="..." +``` + +On Windows PowerShell, use `$env:OPENAI_API_KEY = "sk-..."` instead of `export`. + +### Step 3: Run the demo + +```bash +python demo/maf_governance_demo.py +``` + +You'll see 4 scenarios: + +| Scenario | What Happens | What Governance Does | +|----------|-------------|---------------------| +| 1. Policy Enforcement | Agent tries to use tools | Policies allow/deny based on YAML rules | +| 2. Capability Sandboxing | Agent tries a blocked tool | Governance blocks it before execution | +| 3. Rogue Agent Detection | Agent behaves suspiciously | Behavioral scoring flags the anomaly | +| 4. Content Filtering | Agent gets a dangerous prompt | Governance blocks it pre-LLM | + +### Step 4: Run adversarial attacks + +```bash +python demo/maf_governance_demo.py --include-attacks +``` + +This adds a 5th scenario that tries to break governance: +- Prompt injection ("ignore all previous instructions...") +- Tool alias bypass (calling a blocked tool by another name) +- Trust score manipulation +- SQL injection + +You'll see each attack attempt and whether governance blocked it. + +### What to look for + +- **⚠ Storage: IN-MEMORY ONLY** warning at startup (expected — demo doesn't persist) +- **⚠ Policy: SAMPLE CONFIG** warning (expected — demo uses sample policies) +- **BLOCKED** messages when governance denies an action +- **Audit entries** count at the end showing all governance decisions were logged + +--- + +## Path 2: Govern Your Own Agent (15 minutes) + +This shows how a real customer would add governance to their existing agent code. + +### Step 1: Install + +```bash +pip install agent-governance-toolkit[full] +``` + +### Step 2: Create a policy file + +Save this as `my-policy.yaml`: + +```yaml +version: "1.0" +name: my-first-policy +description: Basic governance for testing + +kernel: + mode: strict + +policies: + - name: tool-restrictions + description: Control which tools agents can use + deny: + - patterns: + - "execute_shell" + - "run_command" + - "delete_.*" + allow: + - action: "search_web" + - action: "read_file" + - action: "write_report" + limits: + - action: tool_call + max_per_session: 20 + +audit: + enabled: true + level: all +``` + +### Step 3: Use the toolkit in your code + +```python +from agent_os import StatelessKernel, ExecutionContext, Policy + +# Create the governance kernel +kernel = StatelessKernel() + +# Define what this agent is allowed to do +ctx = ExecutionContext( + agent_id="my-test-agent", + policies=[ + Policy.read_only(), # No write operations + Policy.rate_limit(100, "1m"), # Max 100 calls/minute + Policy.require_approval( + actions=["send_email", "deploy_*"], # These need human OK + min_approvals=1, + ), + ], +) + +# This is where your agent's tool call gets intercepted +result = await kernel.execute( + action="search_web", + params={"query": "latest AI news"}, + context=ctx, +) +print(f"Allowed: {result.allowed}") +print(f"Reason: {result.reason}") + +# Try a blocked action +result2 = await kernel.execute( + action="execute_shell", + params={"command": "rm -rf /"}, + context=ctx, +) +print(f"Allowed: {result2.allowed}") # False +print(f"Reason: {result2.reason}") # "Blocked by policy" +``` + +### Step 4: Add to a LangChain/CrewAI/ADK agent + +See the quickstart examples: +- `examples/quickstart/langchain_governed.py` +- `examples/quickstart/crewai_governed.py` +- `examples/quickstart/google_adk_governed.py` +- `examples/quickstart/openai_agents_governed.py` +- `examples/quickstart/autogen_governed.py` + +Each is a single file that creates a governed agent in the respective framework. + +--- + +## Path 3: Test the SQL Policy (Security Focus) + +This tests the specific security policies that were recently hardened. + +### Step 1: Install + +```bash +pip install -e "packages/agent-os[dev]" +``` + +### Step 2: Run the SQL policy tests + +```bash +cd packages/agent-os +python -m pytest modules/control-plane/tests/test_sql_policy.py -v +``` + +You should see 40 tests passing — covering: +- DROP, TRUNCATE, ALTER blocked +- GRANT, REVOKE blocked (privilege escalation) +- CREATE USER blocked (backdoor creation) +- EXEC xp_cmdshell blocked (OS command execution) +- UPDATE without WHERE blocked (mass data modification) +- SELECT, INSERT, UPDATE with WHERE allowed + +### Step 3: Test with custom YAML config + +```python +from agent_control_plane.policy_engine import create_policies_from_config + +# Load the strict SQL policy (SELECT only) +rules = create_policies_from_config("examples/policies/sql-strict.yaml") + +# Or the balanced default +rules = create_policies_from_config("examples/policies/sql-safety.yaml") + +# Or the read-only policy +rules = create_policies_from_config("examples/policies/sql-readonly.yaml") +``` + +--- + +## Path 4: Run the Full Test Suite + +```bash +# Run all 6,100+ tests +cd packages/agent-os && python -m pytest tests/ -q +cd ../agent-mesh && python -m pytest tests/ -q +cd ../agent-hypervisor && python -m pytest tests/ -q +cd ../agent-sre && python -m pytest tests/ -q +cd ../agent-compliance && python -m pytest tests/ -q +``` + +--- + +## What to Test (Test Matrix) + +| Area | How to Test | Expected Result | +|------|------------|-----------------| +| **Install** | `pip install agent-governance-toolkit[full]` | Installs cleanly, no errors | +| **Demo** | `python demo/maf_governance_demo.py` | 4 scenarios run, blocked actions shown | +| **Adversarial** | `python demo/maf_governance_demo.py --include-attacks` | All 4 attacks blocked | +| **Policy loading** | Load YAML from `examples/policies/` | Policies parse without errors | +| **SQL safety** | Run `test_sql_policy.py` | 40 tests pass | +| **Framework integration** | Run any `examples/quickstart/*.py` | Governed agent works end-to-end | +| **Audit trail** | Check `evaluator.get_audit_log()` after actions | All decisions logged with timestamps | +| **Trust identity** | `from agentmesh import AgentIdentity` | Ed25519 DID generated | +| **CLI** | `agent-governance --help` | CLI shows available commands | + +--- + +## Common Issues + +| Problem | Solution | +|---------|----------| +| `ModuleNotFoundError: No module named 'yaml'` | `pip install pyyaml` | +| `ModuleNotFoundError: No module named 'cryptography'` | `pip install cryptography` | +| Demo shows "no backend detected" | Set one of the API key env vars (see Step 2 above) | +| `DeprecationWarning: create_default_policies()` | Expected — use `create_policies_from_config()` instead | +| Tests fail with import errors | Run `pip install -e ".[dev]"` in the package directory | + +--- + +## Architecture Summary + +``` +┌─────────────────────────────────────────────┐ +│ Your Agent (any framework) │ +│ LangChain / CrewAI / ADK / AutoGen / etc. │ +└──────────────────┬──────────────────────────┘ + │ Tool call + ▼ +┌─────────────────────────────────────────────┐ +│ Agent Governance Toolkit │ +│ │ +│ 1. Identity Check (Ed25519 DID) │ +│ 2. Policy Evaluation (YAML/OPA/Cedar) │ +│ 3. Action: ALLOW / DENY / ESCALATE │ +│ 4. Audit Log (tamper-proof) │ +└──────────────────┬──────────────────────────┘ + │ If ALLOWED + ▼ +┌─────────────────────────────────────────────┐ +│ Tool / API / Database │ +└─────────────────────────────────────────────┘ +``` + +--- + +## Questions? + +- **GitHub Discussions**: https://github.com/microsoft/agent-governance-toolkit/discussions +- **Issues**: https://github.com/microsoft/agent-governance-toolkit/issues From b62e0c5a3f490a6a601c21244be7590188eb1c87 Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Fri, 20 Mar 2026 17:50:23 -0700 Subject: [PATCH 02/12] docs: add regulatory alignment table and Purview positioning to README Add EU AI Act, Colorado AI Act, and GPAI obligations timeline with AGT coverage mapping. Reference Microsoft Purview DSPM for AI as complementary data governance layer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index ccba47df..0e10d718 100644 --- a/README.md +++ b/README.md @@ -271,6 +271,18 @@ Works with **12+ agent frameworks** including: | Human-Agent Trust Deficit | ASI-09 | ✅ Full audit trails + flight recorder | | Rogue Agents | ASI-10 | ✅ Kill switch + ring isolation + behavioral anomaly detection | +Full mapping with implementation details and test evidence: **[OWASP-COMPLIANCE.md](docs/OWASP-COMPLIANCE.md)** + +### Regulatory Alignment + +| Regulation | Deadline | AGT Coverage | +|------------|----------|-------------| +| EU AI Act — High-Risk AI (Annex III) | August 2, 2026 | Audit trails (Art. 12), risk management (Art. 9), human oversight (Art. 14) | +| Colorado AI Act (SB 24-205) | June 30, 2026 | Risk assessments, human oversight mechanisms, consumer disclosures | +| EU AI Act — GPAI Obligations | Active | Transparency, copyright policies, systemic risk assessment | + +AGT provides **runtime governance** — what agents are allowed to do. For **data governance** and regulator-facing evidence export, see [Microsoft Purview DSPM for AI](https://learn.microsoft.com/purview/ai-microsoft-purview) as a complementary layer. + ## Performance Governance adds **< 0.1 ms per action** — roughly 10,000× faster than an LLM API call. From 33df318ac6ebe51f32136775f0ad530b7018e88c Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Sat, 21 Mar 2026 09:03:02 -0700 Subject: [PATCH 03/12] fix(ci): restore read-all at workflow level for Scorecard verification The Scorecard API rejects workflows with write permissions at the workflow level. id-token: write and security-events: write must be scoped to the job level only. Restores permissions: read-all at workflow level while keeping job-level write permissions intact. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/scorecard.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 5d81e4bf..d5be880a 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -6,12 +6,9 @@ on: schedule: - cron: "15 7 * * 1" -# Minimum permissions required by OpenSSF Scorecard -permissions: - security-events: write - id-token: write - contents: read - actions: read +# Workflow-level permissions must be read-only for Scorecard verification. +# Write permissions are scoped to the job level below. +permissions: read-all jobs: analysis: From f7d49a9ea54807f9f901701809e45ec0bf8814a5 Mon Sep 17 00:00:00 2001 From: Parsa Faraji Alamouti <165321600+parsa-faraji@users.noreply.github.com> Date: Sat, 21 Mar 2026 09:10:46 -0700 Subject: [PATCH 04/12] docs: add comprehensive docstrings to mcp_adapter.py classes (#324) Add Google-style docstrings with Args, Returns, Raises, Attributes, and Example sections to MCPMessageType, MCPAdapter, and MCPServer classes. Also enhances docstrings for key methods including handle_message, _handle_tools_call, _handle_resources_read, and _map_tool_to_action. Fixes #316 --- .../src/agent_control_plane/mcp_adapter.py | 194 +++++++++++++++--- 1 file changed, 164 insertions(+), 30 deletions(-) diff --git a/packages/agent-os/modules/control-plane/src/agent_control_plane/mcp_adapter.py b/packages/agent-os/modules/control-plane/src/agent_control_plane/mcp_adapter.py index ad9dc6fe..b76db05f 100644 --- a/packages/agent-os/modules/control-plane/src/agent_control_plane/mcp_adapter.py +++ b/packages/agent-os/modules/control-plane/src/agent_control_plane/mcp_adapter.py @@ -45,7 +45,26 @@ class MCPMessageType(Enum): - """MCP protocol message types""" + """MCP protocol message types. + + Enumerates the JSON-RPC methods defined by the Model Context Protocol + specification. Each value corresponds to a method string sent in the + ``"method"`` field of an MCP JSON-RPC 2.0 request. + + Attributes: + TOOLS_LIST: List available tools on the server. + TOOLS_CALL: Invoke a registered tool by name. + RESOURCES_LIST: List available resources (files, databases, etc.). + RESOURCES_READ: Read the contents of a specific resource URI. + PROMPTS_LIST: List available prompt templates. + PROMPTS_GET: Retrieve a specific prompt template by name. + COMPLETION: Request a completion (reserved for future use). + + Example: + >>> msg_type = MCPMessageType.TOOLS_CALL + >>> msg_type.value + 'tools/call' + """ TOOLS_LIST = "tools/list" TOOLS_CALL = "tools/call" RESOURCES_LIST = "resources/list" @@ -75,19 +94,60 @@ class MCPMessageType(Enum): class MCPAdapter: - """ - MCP Protocol Adapter with Agent Control Plane Governance. - - This adapter intercepts MCP protocol messages and applies governance - rules before forwarding to the actual MCP server or client. - - MCP uses JSON-RPC 2.0 for communication, with specific methods like: - - tools/list: List available tools - - tools/call: Execute a tool - - resources/list: List available resources - - resources/read: Read a resource - - The adapter ensures all operations respect agent permissions. + """MCP Protocol Adapter with Agent Control Plane Governance. + + Intercepts MCP protocol messages and applies governance rules before + forwarding to the actual MCP server or client. MCP uses JSON-RPC 2.0 + for communication, with specific methods like: + + - ``tools/list``: List available tools + - ``tools/call``: Execute a tool + - ``resources/list``: List available resources + - ``resources/read``: Read a resource + + The adapter ensures all operations respect agent permissions and + policies defined in the control plane. Unknown tools are denied by + default (secure-by-default). + + Args: + control_plane: The ``AgentControlPlane`` instance for governance. + agent_context: The ``AgentContext`` for the agent using this adapter. + mcp_handler: Optional upstream MCP message handler to delegate to + after governance checks pass. + tool_mapping: Optional custom mapping from tool names to + ``ActionType`` values. Merged with ``DEFAULT_MCP_MAPPING``. + on_block: Optional callback invoked when an action is blocked. + Receives ``(tool_name, arguments, check_result)``. + logger: Optional logger instance. + + Attributes: + registered_tools: Dictionary of tool name to tool metadata. + registered_resources: Dictionary of URI pattern to resource metadata. + tool_mapping: Combined mapping of tool/operation names to + ``ActionType`` values used for governance decisions. + + Example: + >>> from agent_control_plane import AgentControlPlane + >>> from agent_control_plane.mcp_adapter import MCPAdapter + >>> + >>> cp = AgentControlPlane() + >>> ctx = cp.create_agent("my-agent") + >>> adapter = MCPAdapter(control_plane=cp, agent_context=ctx) + >>> + >>> # Register a tool + >>> adapter.register_tool("read_file", { + ... "name": "read_file", + ... "description": "Read a file from disk", + ... "inputSchema": {"type": "object", "properties": {"path": {"type": "string"}}} + ... }) + >>> + >>> # Handle an MCP request — governance is applied automatically + >>> response = adapter.handle_message({ + ... "jsonrpc": "2.0", + ... "id": 1, + ... "method": "tools/call", + ... "params": {"name": "read_file", "arguments": {"path": "/tmp/data.txt"}} + ... }) """ def __init__( @@ -130,17 +190,24 @@ def __init__( ) def handle_message(self, message: Dict[str, Any]) -> Dict[str, Any]: - """ - Handle an MCP protocol message with governance. - + """Handle an MCP protocol message with governance. + This is the main entry point for MCP messages. It parses the - JSON-RPC message, applies governance, and returns the result. - + JSON-RPC message, applies governance checks via the control plane, + and returns the result. + Args: - message: MCP JSON-RPC 2.0 message - + message: MCP JSON-RPC 2.0 message containing ``jsonrpc``, + ``method``, ``params``, and ``id`` fields. + Returns: - JSON-RPC 2.0 response + A JSON-RPC 2.0 response dict. On success, contains a + ``"result"`` key. On failure (governance block or error), + contains an ``"error"`` key with ``"code"`` and ``"message"``. + + Raises: + PermissionError: Internally raised when governance blocks an + action; caught and converted to a JSON-RPC error response. """ # Parse the JSON-RPC message jsonrpc = message.get("jsonrpc", "2.0") @@ -198,7 +265,22 @@ def _handle_tools_list(self, params: Dict) -> Dict: return {"tools": allowed_tools} def _handle_tools_call(self, params: Dict) -> Dict: - """Handle tools/call - execute a tool with governance.""" + """Handle tools/call — execute a tool with governance. + + Maps the tool name to an ``ActionType``, checks permissions via + the control plane, and either delegates to the registered handler + or returns the control plane result. + + Args: + params: JSON-RPC params containing ``"name"`` and ``"arguments"``. + + Returns: + Tool execution result dict with MCP ``content`` format. + + Raises: + PermissionError: If the tool is unknown or governance denies + the action. + """ tool_name = params.get("name", "") arguments = params.get("arguments", {}) @@ -259,7 +341,20 @@ def _handle_resources_list(self, params: Dict) -> Dict: return {"resources": allowed_resources} def _handle_resources_read(self, params: Dict) -> Dict: - """Handle resources/read - read a resource with governance.""" + """Handle resources/read — read a resource with governance. + + Determines the ``ActionType`` from the URI scheme and checks + permissions before returning resource contents. + + Args: + params: JSON-RPC params containing ``"uri"``. + + Returns: + Resource contents dict with MCP ``contents`` format. + + Raises: + PermissionError: If governance denies the resource read. + """ uri = params.get("uri", "") self.logger.info(f"Resource read request: {uri}") @@ -321,7 +416,21 @@ def _handle_prompts_get(self, params: Dict) -> Dict: } def _map_tool_to_action(self, tool_name: str) -> Optional[ActionType]: - """Map an MCP tool name to an ActionType.""" + """Map an MCP tool name to an ``ActionType``. + + Resolution order: + 1. Exact match in ``self.tool_mapping`` (case-insensitive). + 2. Pattern-based heuristics (e.g. names containing ``"read"`` + and ``"file"`` map to ``FILE_READ``). + 3. Returns ``None`` for unrecognized tools (deny-by-default). + + Args: + tool_name: The MCP tool name to resolve. + + Returns: + The corresponding ``ActionType``, or ``None`` if the tool + cannot be mapped (triggering a denial). + """ tool_name_lower = tool_name.lower() # Check exact match @@ -411,11 +520,36 @@ def add_tool_mapping(self, tool_name: str, action_type: ActionType): class MCPServer: - """ - Simplified MCP Server with built-in governance. - - This class provides a simple way to create an MCP-compliant server - with Agent Control Plane governance built in. + """Simplified MCP Server with built-in governance. + + Provides a high-level API for creating an MCP-compliant server with + Agent Control Plane governance built in. Wraps an ``MCPAdapter`` + internally and exposes convenience methods for tool and resource + registration. + + Args: + server_name: Human-readable name for this MCP server. + control_plane: ``AgentControlPlane`` instance for governance. + agent_context: ``AgentContext`` representing the server's agent. + transport: Transport method — ``"stdio"`` (default) or ``"sse"``. + logger: Optional logger instance. + + Attributes: + adapter: The underlying ``MCPAdapter`` that handles governance. + server_name: Name of this server. + transport: Active transport method. + + Example: + >>> from agent_control_plane import AgentControlPlane + >>> from agent_control_plane.mcp_adapter import MCPServer + >>> + >>> cp = AgentControlPlane() + >>> ctx = cp.create_agent("file-agent") + >>> server = MCPServer("file-server", cp, ctx, transport="stdio") + >>> + >>> server.register_tool("read_file", handle_read, "Read a file") + >>> server.register_resource("file://", handle_resource, "File resources") + >>> server.start() # All calls are now governed """ def __init__( From baeed605e345192c2e3f3c771bf4e8bf3780d7a5 Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Sat, 21 Mar 2026 09:10:51 -0700 Subject: [PATCH 05/12] ci: add markdown link checker workflow (#323) Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> --- .github/workflows/link-check.yml | 26 ++++++++++++++++++++ .lychee.toml | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 .github/workflows/link-check.yml create mode 100644 .lychee.toml diff --git a/.github/workflows/link-check.yml b/.github/workflows/link-check.yml new file mode 100644 index 00000000..185b1b27 --- /dev/null +++ b/.github/workflows/link-check.yml @@ -0,0 +1,26 @@ +# Checks all Markdown files for broken links (internal and external). +# Uses lychee (https://github.com/lycheeverse/lychee) with configuration +# from .lychee.toml at the repository root. + +name: Link Check + +on: + pull_request: + branches: [main] + +permissions: + contents: read + +jobs: + link-check: + name: Check Markdown links + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - uses: lycheeverse/lychee-action@8646ba30535128ac92d33dfc9133794bfdd9b411 # v2.8.0 + with: + args: >- + --no-progress + '**/*.md' + fail: true diff --git a/.lychee.toml b/.lychee.toml new file mode 100644 index 00000000..fc225190 --- /dev/null +++ b/.lychee.toml @@ -0,0 +1,41 @@ +# Configuration for lychee link checker +# https://lychee.cli.rs/configuration/ + +# General settings +max_concurrency = 32 +timeout = 30 +max_retries = 3 +retry_wait = 5 + +# Accept these HTTP status codes as valid +accept = [200, 429] + +# Exclude patterns for known false positives +exclude = [ + # Placeholder / example URLs + "example\\.com", + "example\\.org", + "example\\.net", + + # Localhost and private networks + "localhost", + "127\\.0\\.0\\.1", + "0\\.0\\.0\\.0", + + # npm registry (frequently rate-limits CI) + "npmjs\\.com", + + # PyPI (frequently rate-limits CI) + "pypi\\.org/project", + + # Microsoft login / auth endpoints (require authentication) + "login\\.microsoftonline\\.com", + "portal\\.azure\\.com", + + # GitHub special URLs that require authentication or don't resolve in CI + "github\\.com/.*/compare/", + "github\\.com/.*/releases/new", +] + +# Exclude email addresses from checking +exclude_mail = true From 8ee3c81a22db02f67ee68f46e13ad2b875497020 Mon Sep 17 00:00:00 2001 From: Zeel Desai <72783325+zeel2104@users.noreply.github.com> Date: Sat, 21 Mar 2026 12:10:55 -0400 Subject: [PATCH 06/12] feat: add policy evaluation heatmap to SRE dashboard (#309) (#326) --- packages/agent-sre/examples/dashboard/app.py | 258 ++++++++++++++++++- 1 file changed, 255 insertions(+), 3 deletions(-) diff --git a/packages/agent-sre/examples/dashboard/app.py b/packages/agent-sre/examples/dashboard/app.py index cdeb5e98..94592909 100644 --- a/packages/agent-sre/examples/dashboard/app.py +++ b/packages/agent-sre/examples/dashboard/app.py @@ -345,6 +345,106 @@ def gen_rollout_data() -> dict: } +POLICIES = [ + "content-safety", + "rate-limit", + "cost-budget", + "pii-filter", + "tool-access", + "hallucination-guard", + "auth-scope", + "output-filter", +] + + +def gen_policy_heatmap_data( + view: str = "agent_x_time", +) -> tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]: + """Return (eval_heatmap_df, violation_heatmap_df, summary_df) for policy heatmap widget. + + ``view`` is either ``'agent_x_time'`` (agents × time buckets) or + ``'policy_x_time'`` (policies × time buckets). + Data is sourced from governance metrics via OpenTelemetry conventions; + here we generate realistic simulated values in the same shape the OTel + exporter would produce. + """ + hours = HOURS[time_range] + # Bucket width: 1 h buckets for short ranges, 4 h or day buckets for long. + if hours <= 6: + n_buckets = hours + bucket_label = "hour" + elif hours <= 48: + n_buckets = hours + bucket_label = "hour" + else: + n_buckets = hours // 4 + bucket_label = "4-hour" + + n_buckets = min(n_buckets, 48) # cap display columns + + end = dt.datetime.now(tz=dt.timezone.utc).replace(minute=0, second=0, microsecond=0) + buckets = [end - dt.timedelta(hours=(n_buckets - 1 - i)) for i in range(n_buckets)] + bucket_labels = [b.strftime("%m/%d %H:%M") for b in buckets] + + if view == "agent_x_time": + rows_eval: list[dict] = [] + rows_viol: list[dict] = [] + for agent in selected_agents: + # Each agent has a characteristic baseline rate and occasional spikes + base_eval = rng.uniform(20, 200) + base_viol = rng.uniform(0.01, 0.12) # violation fraction + spike_at = rng.integers(0, max(1, n_buckets - 1)) + for i, label in enumerate(bucket_labels): + spike = 4.0 if i == spike_at else 1.0 + eval_count = int(base_eval * spike * rng.uniform(0.7, 1.3)) + viol_count = int(eval_count * base_viol * spike * rng.uniform(0.5, 1.5)) + rows_eval.append({"y": agent, "x": label, "z": eval_count}) + rows_viol.append({"y": agent, "x": label, "z": viol_count}) + eval_df = pd.DataFrame(rows_eval) + viol_df = pd.DataFrame(rows_viol) + y_label = "Agent" + else: + rows_eval = [] + rows_viol = [] + for policy in POLICIES: + base_eval = rng.uniform(10, 300) + base_viol = rng.uniform(0.005, 0.20) + spike_at = rng.integers(0, max(1, n_buckets - 1)) + for i, label in enumerate(bucket_labels): + spike = 5.0 if i == spike_at else 1.0 + eval_count = int(base_eval * spike * rng.uniform(0.6, 1.4)) + viol_count = int(eval_count * base_viol * spike * rng.uniform(0.5, 2.0)) + rows_eval.append({"y": policy, "x": label, "z": eval_count}) + rows_viol.append({"y": policy, "x": label, "z": viol_count}) + eval_df = pd.DataFrame(rows_eval) + viol_df = pd.DataFrame(rows_viol) + y_label = "Policy" + + # Summary table + if view == "agent_x_time": + entities = selected_agents + else: + entities = POLICIES + + summary_rows = [] + for entity in entities: + evals = eval_df[eval_df["y"] == entity]["z"].sum() + viols = viol_df[viol_df["y"] == entity]["z"].sum() + peak_bucket = eval_df[eval_df["y"] == entity].nlargest(1, "z")["x"].values + summary_rows.append( + { + y_label: entity, + "Total Evaluations": int(evals), + "Total Violations": int(viols), + "Violation Rate": f"{viols / max(evals, 1):.2%}", + "Peak Bucket": peak_bucket[0] if len(peak_bucket) else "—", + } + ) + summary_df = pd.DataFrame(summary_rows).sort_values("Total Violations", ascending=False) + + return eval_df, viol_df, summary_df + + # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- @@ -401,8 +501,8 @@ def _gauge(value: float, title: str, thresholds: tuple[float, float] = (2.0, 6.0 # --------------------------------------------------------------------------- # TABS # --------------------------------------------------------------------------- -tab_slo, tab_cost, tab_chaos, tab_inc, tab_delivery = st.tabs( - ["📊 SLO Health", "💰 Cost Management", "🧪 Chaos Engineering", "🚨 Incidents", "🚀 Progressive Delivery"] +tab_slo, tab_cost, tab_chaos, tab_inc, tab_delivery, tab_policy = st.tabs( + ["📊 SLO Health", "💰 Cost Management", "🧪 Chaos Engineering", "🚨 Incidents", "🚀 Progressive Delivery", "🔥 Policy Heatmap"] ) # ========================== TAB 1: SLO Health ============================== @@ -821,9 +921,161 @@ def _gauge(value: float, title: str, thresholds: tuple[float, float] = (2.0, 6.0 ] st.dataframe(pd.DataFrame(events), use_container_width=True, hide_index=True) +# ========================== TAB 6: Policy Heatmap ========================== +with tab_policy: + st.subheader("🔥 Policy Evaluation Heatmap") + st.caption( + "Visualises governance metric density from the OpenTelemetry pipeline. " + "Color intensity reflects evaluation count or violation count per time bucket. " + "Use the controls below to switch between views." + ) + + ctrl_left, ctrl_right = st.columns([2, 3]) + with ctrl_left: + heatmap_view = st.radio( + "Heatmap axes", + ["agent_x_time", "policy_x_time"], + format_func=lambda v: "Agent × Time" if v == "agent_x_time" else "Policy × Time", + horizontal=True, + ) + with ctrl_right: + heatmap_metric = st.radio( + "Color metric", + ["evaluations", "violations"], + format_func=lambda v: "Evaluation Count" if v == "evaluations" else "Violation Count", + horizontal=True, + ) + + eval_df, viol_df, summary_df = gen_policy_heatmap_data(view=heatmap_view) + plot_df = eval_df if heatmap_metric == "evaluations" else viol_df + color_label = "Evaluations" if heatmap_metric == "evaluations" else "Violations" + color_scale = "Blues" if heatmap_metric == "evaluations" else "Reds" + y_axis_label = "Agent" if heatmap_view == "agent_x_time" else "Policy" + + # Pivot to matrix form for imshow + pivot = plot_df.pivot(index="y", columns="x", values="z").fillna(0) + + fig_heatmap = go.Figure( + go.Heatmap( + z=pivot.values, + x=list(pivot.columns), + y=list(pivot.index), + colorscale=color_scale, + hoverongaps=False, + hovertemplate=( + f"{y_axis_label}: %{{y}}
" + "Time: %{x}
" + f"{color_label}: %{{z:,}}" + ), + colorbar=dict( + title=dict(text=color_label, side="right"), + thickness=14, + ), + ) + ) + fig_heatmap.update_layout( + template=PLOTLY_TEMPLATE, + height=max(300, len(pivot) * 38 + 80), + margin=dict(l=20, r=20, t=30, b=80), + xaxis=dict( + title="Time bucket", + tickangle=-45, + tickfont=dict(size=10), + side="bottom", + ), + yaxis=dict(title=y_axis_label, autorange="reversed"), + paper_bgcolor="rgba(0,0,0,0)", + plot_bgcolor="rgba(0,0,0,0)", + ) + st.plotly_chart(fig_heatmap, use_container_width=True) + + # KPI strip + total_evals = int(eval_df["z"].sum()) + total_viols = int(viol_df["z"].sum()) + overall_viol_rate = total_viols / max(total_evals, 1) + peak_row = eval_df.loc[eval_df["z"].idxmax()] + peak_entity = peak_row["y"] + peak_time = peak_row["x"] + + k1, k2, k3, k4 = st.columns(4) + k1.metric("Total Evaluations", f"{total_evals:,}") + k2.metric( + "Total Violations", + f"{total_viols:,}", + delta=f"{overall_viol_rate:.2%} rate", + delta_color="inverse", + ) + k3.metric( + "Peak Activity", + peak_entity, + delta=peak_time, + help="Entity with the highest single-bucket evaluation count", + ) + k4.metric( + "Violation Rate", + f"{overall_viol_rate:.2%}", + delta=f"{(overall_viol_rate - 0.05):.2%} vs 5% baseline", + delta_color="inverse", + ) + + st.divider() + + # Side-by-side: eval vs violation distribution + left_col, right_col = st.columns(2) + + with left_col: + st.subheader("Evaluation Distribution") + agg_eval = eval_df.groupby("y")["z"].sum().reset_index().sort_values("z", ascending=True) + fig_eval_bar = go.Figure( + go.Bar( + y=agg_eval["y"], + x=agg_eval["z"], + orientation="h", + marker_color=COLOR_INFO, + hovertemplate=f"%{{y}}
Evaluations: %{{x:,}}", + ) + ) + fig_eval_bar.update_layout( + template=PLOTLY_TEMPLATE, + height=max(220, len(agg_eval) * 32), + margin=dict(l=10, r=20, t=10, b=30), + xaxis_title="Evaluations", + yaxis_title=y_axis_label, + ) + st.plotly_chart(fig_eval_bar, use_container_width=True) + + with right_col: + st.subheader("Violation Distribution") + agg_viol = viol_df.groupby("y")["z"].sum().reset_index().sort_values("z", ascending=True) + fig_viol_bar = go.Figure( + go.Bar( + y=agg_viol["y"], + x=agg_viol["z"], + orientation="h", + marker_color=COLOR_CRITICAL, + hovertemplate=f"%{{y}}
Violations: %{{x:,}}", + ) + ) + fig_viol_bar.update_layout( + template=PLOTLY_TEMPLATE, + height=max(220, len(agg_viol) * 32), + margin=dict(l=10, r=20, t=10, b=30), + xaxis_title="Violations", + yaxis_title=y_axis_label, + ) + st.plotly_chart(fig_viol_bar, use_container_width=True) + + st.subheader("Summary Table") + st.caption( + "Sorted by total violations. 'Peak Bucket' shows the time window with the " + "highest evaluation count — useful for spotting recurring patterns (e.g. " + "every Tuesday at 3 PM)." + ) + st.dataframe(summary_df, use_container_width=True, hide_index=True) + # --------------------------------------------------------------------------- # Auto-refresh # --------------------------------------------------------------------------- if auto_refresh: time.sleep(30) - st.rerun() + st.rerun() \ No newline at end of file From 057b908f5157f515f2aac85639a53a848bf096e1 Mon Sep 17 00:00:00 2001 From: Xavier Garceau-Aranda Date: Sat, 21 Mar 2026 17:11:33 +0100 Subject: [PATCH 07/12] fix: remove unregistered PyPI packages from notebooks and requirements (dependency confusion) (#325) - Replace !pip install agent-os with !pip install -e ../.. in all 6 notebooks; agent-os is not on PyPI and installing it from PyPI is a dependency confusion vector - Replace zendesk-sdk/freshdesk-sdk with zenpy/freshdesk (the real published SDKs) in customer-service/requirements.txt - Remove hashlib-compat from healthcare-hipaa/requirements.txt; hashlib is stdlib and hashlib-compat is not a real PyPI package --- .../customer-service/requirements.txt | 6 +- .../healthcare-hipaa/requirements.txt | 3 +- .../notebooks/01-hello-agent-os.ipynb | 36 +++++----- .../notebooks/02-episodic-memory-demo.ipynb | 60 ++++++++-------- .../notebooks/03-time-travel-debugging.ipynb | 68 +++++++++--------- .../04-cross-model-verification.ipynb | 72 +++++++++---------- .../05-multi-agent-coordination.ipynb | 50 ++++++------- .../agent-os/notebooks/06-policy-engine.ipynb | 50 ++++++------- 8 files changed, 174 insertions(+), 171 deletions(-) diff --git a/packages/agent-os/examples/customer-service/requirements.txt b/packages/agent-os/examples/customer-service/requirements.txt index 7cbe6688..034f3753 100644 --- a/packages/agent-os/examples/customer-service/requirements.txt +++ b/packages/agent-os/examples/customer-service/requirements.txt @@ -9,8 +9,10 @@ openai>=1.0.0 anthropic>=0.18.0 # Ticket systems -zendesk-sdk>=1.0.0 -freshdesk-sdk>=2.0.0 +# zendesk-sdk is NOT on PyPI — use 'zenpy' for the Zendesk API client +zenpy>=2.0.0 +# freshdesk-sdk is NOT on PyPI — use 'freshdesk' for the Freshdesk API client +freshdesk>=0.1.0 # Knowledge base pinecone-client>=3.0.0 diff --git a/packages/agent-os/examples/healthcare-hipaa/requirements.txt b/packages/agent-os/examples/healthcare-hipaa/requirements.txt index f1402933..d6929f08 100644 --- a/packages/agent-os/examples/healthcare-hipaa/requirements.txt +++ b/packages/agent-os/examples/healthcare-hipaa/requirements.txt @@ -29,7 +29,8 @@ structlog>=24.1.0 python-json-logger>=2.0.0 # Compliance -hashlib-compat>=1.0.0 +# hashlib-compat is NOT a real package — hashlib is part of Python's standard library +# and requires no installation. Remove this line. # Monitoring prometheus-client>=0.19.0 diff --git a/packages/agent-os/notebooks/01-hello-agent-os.ipynb b/packages/agent-os/notebooks/01-hello-agent-os.ipynb index fad8b3b9..59caef54 100644 --- a/packages/agent-os/notebooks/01-hello-agent-os.ipynb +++ b/packages/agent-os/notebooks/01-hello-agent-os.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 🚀 Hello Agent OS\n", + "# \ud83d\ude80 Hello Agent OS\n", "\n", "> **Your first governed agent in under 5 minutes.**\n", "\n", @@ -34,7 +34,7 @@ "metadata": {}, "outputs": [], "source": [ - "!pip install agent-os --quiet" + "!pip install -e ../.. --quiet" ] }, { @@ -57,7 +57,7 @@ "# Create a kernel with strict policy enforcement\n", "kernel = KernelSpace(policy=\"strict\")\n", "\n", - "print(\"✅ Kernel initialized with 'strict' policy\")\n", + "print(\"\u2705 Kernel initialized with 'strict' policy\")\n", "print(f\" Policy mode: {kernel.policy.mode}\")" ] }, @@ -87,7 +87,7 @@ " result = f\"Hello! I processed your task: {task}\"\n", " return result\n", "\n", - "print(\"✅ Agent registered with kernel\")" + "print(\"\u2705 Agent registered with kernel\")" ] }, { @@ -110,27 +110,27 @@ "# Execute the agent\n", "result = await kernel.execute(hello_agent, \"Summarize today's news\")\n", "\n", - "print(f\"\\n📤 Result: {result}\")" + "print(f\"\\n\ud83d\udce4 Result: {result}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 🎉 Congratulations!\n", + "## \ud83c\udf89 Congratulations!\n", "\n", "You just ran your first governed agent. Here's what happened:\n", "\n", "```\n", - "┌─────────────────────────────────────────────────────────┐\n", - "│ USER SPACE │\n", - "│ hello_agent() executed here │\n", - "├─────────────────────────────────────────────────────────┤\n", - "│ KERNEL SPACE │\n", - "│ ✓ Action checked against 'strict' policy │\n", - "│ ✓ No violations detected │\n", - "│ ✓ Result returned to user space │\n", - "└─────────────────────────────────────────────────────────┘\n", + "\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n", + "\u2502 USER SPACE \u2502\n", + "\u2502 hello_agent() executed here \u2502\n", + "\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n", + "\u2502 KERNEL SPACE \u2502\n", + "\u2502 \u2713 Action checked against 'strict' policy \u2502\n", + "\u2502 \u2713 No violations detected \u2502\n", + "\u2502 \u2713 Result returned to user space \u2502\n", + "\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n", "```\n", "\n", "---" @@ -162,7 +162,7 @@ " \n", " return \"File written successfully\"\n", "\n", - "print(\"⚠️ Agent registered - but it will be blocked...\")" + "print(\"\u26a0\ufe0f Agent registered - but it will be blocked...\")" ] }, { @@ -176,7 +176,7 @@ " result = await kernel.execute(dangerous_agent, \"Write some data\")\n", " print(f\"Result: {result}\")\n", "except Exception as e:\n", - " print(f\"🛑 BLOCKED: {e}\")\n", + " print(f\"\ud83d\uded1 BLOCKED: {e}\")\n", " print(\"\\nThe kernel prevented the file write before it executed!\")" ] }, @@ -281,4 +281,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} +} \ No newline at end of file diff --git a/packages/agent-os/notebooks/02-episodic-memory-demo.ipynb b/packages/agent-os/notebooks/02-episodic-memory-demo.ipynb index f4b401b2..9c8b0245 100644 --- a/packages/agent-os/notebooks/02-episodic-memory-demo.ipynb +++ b/packages/agent-os/notebooks/02-episodic-memory-demo.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 🧠 Episodic Memory Demo\n", + "# \ud83e\udde0 Episodic Memory Demo\n", "\n", "> **Give your agents memory that persists and learns.**\n", "\n", @@ -32,12 +32,12 @@ "\n", "```\n", "Traditional DB: Episodic Memory:\n", - "┌─────────────┐ ┌─────────────┐\n", - "│ UPDATE ✓ │ │ APPEND ONLY │\n", - "│ DELETE ✓ │ │ NO UPDATE │\n", - "│ MODIFY ✓ │ │ NO DELETE │\n", - "└─────────────┘ └─────────────┘\n", - " ↓ ↓\n", + "\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n", + "\u2502 UPDATE \u2713 \u2502 \u2502 APPEND ONLY \u2502\n", + "\u2502 DELETE \u2713 \u2502 \u2502 NO UPDATE \u2502\n", + "\u2502 MODIFY \u2713 \u2502 \u2502 NO DELETE \u2502\n", + "\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n", + " \u2193 \u2193\n", " Audit gaps Full history\n", " State bugs Time-travel OK\n", "```\n", @@ -58,7 +58,7 @@ "metadata": {}, "outputs": [], "source": [ - "!pip install agent-os emk --quiet" + "!pip install -e ../.. emk --quiet" ] }, { @@ -91,7 +91,7 @@ "# Store it (immutable - can never be changed)\n", "store.store(episode)\n", "\n", - "print(\"✅ Episode stored!\")\n", + "print(\"\u2705 Episode stored!\")\n", "print(f\" ID: {episode.id}\")\n", "print(f\" Timestamp: {episode.timestamp}\")\n", "print(f\" Goal: {episode.goal}\")" @@ -142,9 +142,9 @@ "\n", "for ep in episodes:\n", " store.store(ep)\n", - " print(f\"✅ Stored: {ep.goal[:40]}...\")\n", + " print(f\"\u2705 Stored: {ep.goal[:40]}...\")\n", "\n", - "print(f\"\\n📊 Total episodes in memory: {len(store)}\")" + "print(f\"\\n\ud83d\udcca Total episodes in memory: {len(store)}\")" ] }, { @@ -165,10 +165,10 @@ "# Get all episodes\n", "all_episodes = store.list_all()\n", "\n", - "print(\"📜 All Episodes:\")\n", + "print(\"\ud83d\udcdc All Episodes:\")\n", "print(\"-\" * 60)\n", "for ep in all_episodes:\n", - " status = \"❌\" if \"FAILED\" in ep.result else \"✅\"\n", + " status = \"\u274c\" if \"FAILED\" in ep.result else \"\u2705\"\n", " print(f\"{status} {ep.timestamp.strftime('%Y-%m-%d %H:%M')} | {ep.goal[:40]}\")" ] }, @@ -191,11 +191,11 @@ "query = \"How to optimize slow database queries?\"\n", "similar = store.retrieve(query=query, k=3)\n", "\n", - "print(f\"🔍 Query: {query}\")\n", - "print(\"\\n📚 Relevant memories:\")\n", + "print(f\"\ud83d\udd0d Query: {query}\")\n", + "print(\"\\n\ud83d\udcda Relevant memories:\")\n", "print(\"-\" * 60)\n", "for ep in similar:\n", - " print(f\"\\n🎯 Goal: {ep.goal}\")\n", + " print(f\"\\n\ud83c\udfaf Goal: {ep.goal}\")\n", " print(f\" Action: {ep.action}\")\n", " print(f\" Learning: {ep.reflection}\")" ] @@ -229,7 +229,7 @@ ")\n", "\n", "store.store(failed_episode)\n", - "print(\"❌ Failure recorded!\")\n", + "print(\"\u274c Failure recorded!\")\n", "print(f\" Reason: {failed_episode.failure_reason}\")" ] }, @@ -242,14 +242,14 @@ "# Retrieve both successes and failures\n", "patterns = store.retrieve_with_anti_patterns()\n", "\n", - "print(\"📊 Memory Analysis:\")\n", - "print(f\" ✅ Successes: {len(patterns['successes'])}\")\n", - "print(f\" ❌ Failures: {len(patterns['failures'])}\")\n", + "print(\"\ud83d\udcca Memory Analysis:\")\n", + "print(f\" \u2705 Successes: {len(patterns['successes'])}\")\n", + "print(f\" \u274c Failures: {len(patterns['failures'])}\")\n", "\n", "if patterns['failures']:\n", - " print(\"\\n⚠️ Things to avoid:\")\n", + " print(\"\\n\u26a0\ufe0f Things to avoid:\")\n", " for fail in patterns['failures']:\n", - " print(f\" • {fail.goal}: {fail.failure_reason}\")" + " print(f\" \u2022 {fail.goal}: {fail.failure_reason}\")" ] }, { @@ -278,7 +278,7 @@ "# Run compression\n", "result = compressor.compress_old_episodes()\n", "\n", - "print(\"🌙 Sleep Cycle Complete!\")\n", + "print(\"\ud83c\udf19 Sleep Cycle Complete!\")\n", "print(f\" Episodes processed: {result['episodes_processed']}\")\n", "print(f\" Rules generated: {result['rules_generated']}\")\n", "print(f\" Storage saved: {result['storage_saved_percent']}%\")" @@ -291,11 +291,11 @@ "outputs": [], "source": [ "# View generated rules\n", - "print(\"📖 Semantic Rules (distilled knowledge):\")\n", + "print(\"\ud83d\udcd6 Semantic Rules (distilled knowledge):\")\n", "print(\"-\" * 60)\n", "for rule in result['rules']:\n", - " print(f\"\\n• {rule['pattern']}\")\n", - " print(f\" → {rule['insight']}\")" + " print(f\"\\n\u2022 {rule['pattern']}\")\n", + " print(f\" \u2192 {rule['insight']}\")" ] }, { @@ -328,7 +328,7 @@ " \n", " # 2. Build context from past experiences\n", " context = \"\\n\".join([\n", - " f\"Past: {ep.goal} → {ep.reflection}\" \n", + " f\"Past: {ep.goal} \u2192 {ep.reflection}\" \n", " for ep in relevant\n", " ])\n", " \n", @@ -348,7 +348,7 @@ "\n", "# Execute\n", "result = await kernel.execute(learning_agent, \"Optimize the sales dashboard\")\n", - "print(f\"\\n📤 Result: {result}\")" + "print(f\"\\n\ud83d\udce4 Result: {result}\")" ] }, { @@ -370,7 +370,7 @@ "for f in [\"demo_memory.jsonl\", \"agent_memories.jsonl\"]:\n", " if os.path.exists(f):\n", " os.remove(f)\n", - " print(f\"🗑️ Removed {f}\")" + " print(f\"\ud83d\uddd1\ufe0f Removed {f}\")" ] }, { @@ -432,4 +432,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} +} \ No newline at end of file diff --git a/packages/agent-os/notebooks/03-time-travel-debugging.ipynb b/packages/agent-os/notebooks/03-time-travel-debugging.ipynb index 37171954..af69e857 100644 --- a/packages/agent-os/notebooks/03-time-travel-debugging.ipynb +++ b/packages/agent-os/notebooks/03-time-travel-debugging.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# ⏰ Time-Travel Debugging\n", + "# \u23f0 Time-Travel Debugging\n", "\n", "> **Replay and debug agent decisions step-by-step.**\n", "\n", @@ -26,7 +26,7 @@ "source": [ "## Why Time-Travel Debugging?\n", "\n", - "**Problem:** When an agent makes a bad decision, traditional debugging shows the final state—not how it got there.\n", + "**Problem:** When an agent makes a bad decision, traditional debugging shows the final state\u2014not how it got there.\n", "\n", "**Solution:** Record every decision point. Replay the agent's reasoning at any moment.\n", "\n", @@ -34,14 +34,14 @@ "Traditional Debugging: Time-Travel Debugging:\n", " \n", " Start Start\n", - " ↓ ↓ [recorded]\n", - " Step 1 Step 1 ← replay here\n", - " ↓ ↓ [recorded]\n", - " Step 2 Step 2 ← replay here\n", - " ↓ ↓ [recorded]\n", - " Error! ← see this only Step 3 ← replay here\n", - " ↓ [recorded]\n", - " Error! ← see full context\n", + " \u2193 \u2193 [recorded]\n", + " Step 1 Step 1 \u2190 replay here\n", + " \u2193 \u2193 [recorded]\n", + " Step 2 Step 2 \u2190 replay here\n", + " \u2193 \u2193 [recorded]\n", + " Error! \u2190 see this only Step 3 \u2190 replay here\n", + " \u2193 [recorded]\n", + " Error! \u2190 see full context\n", "```\n", "\n", "---" @@ -60,7 +60,7 @@ "metadata": {}, "outputs": [], "source": [ - "!pip install agent-os --quiet" + "!pip install -e ../.. --quiet" ] }, { @@ -88,7 +88,7 @@ "# Connect recorder to kernel\n", "kernel.attach_recorder(recorder)\n", "\n", - "print(\"✅ Flight Recorder initialized\")\n", + "print(\"\u2705 Flight Recorder initialized\")\n", "print(f\" Storage: ./flight_data\")" ] }, @@ -160,7 +160,7 @@ " \n", " return response\n", "\n", - "print(\"✅ Agent registered with checkpoints\")" + "print(\"\u2705 Agent registered with checkpoints\")" ] }, { @@ -178,7 +178,7 @@ "source": [ "# Start recording session\n", "session_id = recorder.start_session(agent_id=\"analysis_agent\")\n", - "print(f\"🎬 Recording session: {session_id}\")\n", + "print(f\"\ud83c\udfac Recording session: {session_id}\")\n", "\n", "# Execute multiple tasks\n", "tasks = [\n", @@ -189,12 +189,12 @@ "\n", "for task in tasks:\n", " result = await kernel.execute(analysis_agent, task)\n", - " print(f\"\\n📝 Task: {task}\")\n", + " print(f\"\\n\ud83d\udcdd Task: {task}\")\n", " print(f\" Result: {result}\")\n", "\n", "# Stop recording\n", "recorder.stop_session()\n", - "print(f\"\\n🛑 Recording stopped. {recorder.checkpoint_count()} checkpoints saved.\")" + "print(f\"\\n\ud83d\uded1 Recording stopped. {recorder.checkpoint_count()} checkpoints saved.\")" ] }, { @@ -213,9 +213,9 @@ "# Get all checkpoints from the session\n", "checkpoints = recorder.list_checkpoints(session_id)\n", "\n", - "print(f\"📊 Session: {session_id}\")\n", + "print(f\"\ud83d\udcca Session: {session_id}\")\n", "print(f\" Total checkpoints: {len(checkpoints)}\")\n", - "print(\"\\n🔍 Checkpoint Timeline:\")\n", + "print(\"\\n\ud83d\udd0d Checkpoint Timeline:\")\n", "print(\"-\" * 70)\n", "\n", "for i, cp in enumerate(checkpoints):\n", @@ -242,11 +242,11 @@ "# Replay checkpoint by name\n", "checkpoint = recorder.replay(session_id, checkpoint_name=\"analyze_content\")\n", "\n", - "print(\"⏪ REPLAYING: analyze_content\")\n", + "print(\"\u23ea REPLAYING: analyze_content\")\n", "print(\"=\" * 60)\n", - "print(f\"\\n📍 Timestamp: {checkpoint.timestamp}\")\n", - "print(f\"🧠 Reasoning: {checkpoint.reasoning}\")\n", - "print(f\"\\n📦 State at this point:\")\n", + "print(f\"\\n\ud83d\udccd Timestamp: {checkpoint.timestamp}\")\n", + "print(f\"\ud83e\udde0 Reasoning: {checkpoint.reasoning}\")\n", + "print(f\"\\n\ud83d\udce6 State at this point:\")\n", "\n", "import json\n", "print(json.dumps(checkpoint.state, indent=2))" @@ -279,14 +279,14 @@ "# Compare the two paths\n", "comparison = recorder.compare_sessions(session_a, session_b)\n", "\n", - "print(\"📊 Execution Path Comparison\")\n", + "print(\"\ud83d\udcca Execution Path Comparison\")\n", "print(\"=\" * 60)\n", "print(f\"\\nSession A: {session_a}\")\n", "print(f\"Session B: {session_b}\")\n", - "print(f\"\\n🔀 Divergence point: {comparison['divergence_point']}\")\n", - "print(f\"\\n📝 Session A at divergence:\")\n", + "print(f\"\\n\ud83d\udd00 Divergence point: {comparison['divergence_point']}\")\n", + "print(f\"\\n\ud83d\udcdd Session A at divergence:\")\n", "print(f\" Reasoning: {comparison['session_a_state']['reasoning']}\")\n", - "print(f\"\\n📝 Session B at divergence:\")\n", + "print(f\"\\n\ud83d\udcdd Session B at divergence:\")\n", "print(f\" Reasoning: {comparison['session_b_state']['reasoning']}\")" ] }, @@ -331,7 +331,7 @@ "try:\n", " await kernel.execute(buggy_agent, \"test task\")\n", "except ValueError as e:\n", - " print(f\"❌ Error: {e}\")\n", + " print(f\"\u274c Error: {e}\")\n", "finally:\n", " recorder.stop_session()" ] @@ -343,19 +343,19 @@ "outputs": [], "source": [ "# Debug: Replay checkpoints to find the bug\n", - "print(\"🔍 Debugging the failure...\")\n", + "print(\"\ud83d\udd0d Debugging the failure...\")\n", "print(\"=\" * 60)\n", "\n", "checkpoints = recorder.list_checkpoints(session_debug)\n", "\n", "for cp in checkpoints:\n", - " print(f\"\\n📍 Checkpoint: {cp.name}\")\n", + " print(f\"\\n\ud83d\udccd Checkpoint: {cp.name}\")\n", " print(f\" Reasoning: {cp.reasoning}\")\n", " \n", " if 'data' in cp.state:\n", " print(f\" data['processed'] = {cp.state['data'].get('processed')}\")\n", "\n", - "print(\"\\n💡 Bug found! 'processed' is never set to True\")\n", + "print(\"\\n\ud83d\udca1 Bug found! 'processed' is never set to True\")\n", "print(\" Fix: Add 'data[\\\"processed\\\"] = True' after processing\")" ] }, @@ -379,7 +379,7 @@ "with open(\"debug_export.json\", \"w\") as f:\n", " f.write(export_data)\n", "\n", - "print(\"📤 Exported to debug_export.json\")\n", + "print(\"\ud83d\udce4 Exported to debug_export.json\")\n", "print(\" Can be loaded into visualization tools or analyzed offline\")" ] }, @@ -402,11 +402,11 @@ "# Remove demo files\n", "if os.path.exists(\"./flight_data\"):\n", " shutil.rmtree(\"./flight_data\")\n", - " print(\"🗑️ Removed flight_data/\")\n", + " print(\"\ud83d\uddd1\ufe0f Removed flight_data/\")\n", "\n", "if os.path.exists(\"debug_export.json\"):\n", " os.remove(\"debug_export.json\")\n", - " print(\"🗑️ Removed debug_export.json\")" + " print(\"\ud83d\uddd1\ufe0f Removed debug_export.json\")" ] }, { @@ -470,4 +470,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} +} \ No newline at end of file diff --git a/packages/agent-os/notebooks/04-cross-model-verification.ipynb b/packages/agent-os/notebooks/04-cross-model-verification.ipynb index 1c3a1d15..80c70664 100644 --- a/packages/agent-os/notebooks/04-cross-model-verification.ipynb +++ b/packages/agent-os/notebooks/04-cross-model-verification.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 🔍 Verification (CMVK)\n", + "# \ud83d\udd0d Verification (CMVK)\n", "\n", "> **Detect hallucinations by comparing outputs across models.**\n", "\n", @@ -34,12 +34,12 @@ "Single Model: Verification:\n", "\n", " GPT-4 GPT-4 Claude Gemini\n", - " ↓ ↓ ↓ ↓\n", + " \u2193 \u2193 \u2193 \u2193\n", "\"Paris is the \"Paris\" \"Paris\" \"Paris\"\n", - " capital of France\" ↓ ↓ ↓\n", - " ↓ ─────────────────────────\n", + " capital of France\" \u2193 \u2193 \u2193\n", + " \u2193 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", " Trust it? CONSENSUS: 100%\n", - " 🤷 ✅ High confidence\n", + " \ud83e\udd37 \u2705 High confidence\n", "```\n", "\n", "---" @@ -58,7 +58,7 @@ "metadata": {}, "outputs": [], "source": [ - "!pip install agent-os[cmvk] --quiet" + "!pip install -e ..[cmvk] --quiet" ] }, { @@ -84,14 +84,14 @@ "\n", "score = verify(text_a, text_b)\n", "\n", - "print(\"📊 Verification Result\")\n", + "print(\"\ud83d\udcca Verification Result\")\n", "print(\"=\" * 50)\n", "print(f\"Text A: {text_a}\")\n", "print(f\"Text B: {text_b}\")\n", - "print(f\"\\n🎯 Drift Score: {score.drift_score:.3f}\")\n", + "print(f\"\\n\ud83c\udfaf Drift Score: {score.drift_score:.3f}\")\n", "print(f\" (0.0 = identical, 1.0 = completely different)\")\n", - "print(f\"\\n🔒 Confidence: {score.confidence:.3f}\")\n", - "print(f\"📁 Drift Type: {score.drift_type}\")" + "print(f\"\\n\ud83d\udd12 Confidence: {score.confidence:.3f}\")\n", + "print(f\"\ud83d\udcc1 Drift Type: {score.drift_type}\")" ] }, { @@ -106,13 +106,13 @@ "\n", "score = verify(text_a, text_c)\n", "\n", - "print(\"📊 Different Texts\")\n", + "print(\"\ud83d\udcca Different Texts\")\n", "print(\"=\" * 50)\n", "print(f\"Text A: {text_a}\")\n", "print(f\"Text C: {text_c}\")\n", - "print(f\"\\n🎯 Drift Score: {score.drift_score:.3f}\")\n", - "print(f\"📁 Drift Type: {score.drift_type}\")\n", - "print(f\"\\n⚠️ High drift detected! Outputs disagree.\")" + "print(f\"\\n\ud83c\udfaf Drift Score: {score.drift_score:.3f}\")\n", + "print(f\"\ud83d\udcc1 Drift Type: {score.drift_type}\")\n", + "print(f\"\\n\u26a0\ufe0f High drift detected! Outputs disagree.\")" ] }, { @@ -146,7 +146,7 @@ " (\"The quick brown fox\", \"The fast brown fox\", \"LEXICAL\"),\n", "]\n", "\n", - "print(\"📊 Drift Type Examples\")\n", + "print(\"\ud83d\udcca Drift Type Examples\")\n", "print(\"=\" * 70)\n", "\n", "for text_a, text_b, expected_type in examples:\n", @@ -182,15 +182,15 @@ "\n", "# Compare similar embeddings\n", "score_ab = verify_embeddings(embedding_a, embedding_b)\n", - "print(\"📊 Similar Embeddings (A vs B)\")\n", + "print(\"\ud83d\udcca Similar Embeddings (A vs B)\")\n", "print(f\" Drift: {score_ab.drift_score:.4f}\")\n", "print(f\" Method: {score_ab.details.get('method', 'cosine')}\")\n", "\n", "# Compare different embeddings\n", "score_ac = verify_embeddings(embedding_a, embedding_c)\n", - "print(f\"\\n📊 Different Embeddings (A vs C)\")\n", + "print(f\"\\n\ud83d\udcca Different Embeddings (A vs C)\")\n", "print(f\" Drift: {score_ac.drift_score:.4f}\")\n", - "print(f\" ⚠️ Significant drift detected!\")" + "print(f\" \u26a0\ufe0f Significant drift detected!\")" ] }, { @@ -218,13 +218,13 @@ "\n", "# Compare distributions using KL divergence\n", "score_ab = verify_distributions(dist_a, dist_b, method=\"kl\")\n", - "print(\"📊 Similar Distributions (KL Divergence)\")\n", + "print(\"\ud83d\udcca Similar Distributions (KL Divergence)\")\n", "print(f\" Drift: {score_ab.drift_score:.4f}\")\n", "\n", "score_ac = verify_distributions(dist_a, dist_c, method=\"kl\")\n", - "print(f\"\\n📊 Different Distributions (KL Divergence)\")\n", + "print(f\"\\n\ud83d\udcca Different Distributions (KL Divergence)\")\n", "print(f\" Drift: {score_ac.drift_score:.4f}\")\n", - "print(f\" ⚠️ Models disagree significantly!\")" + "print(f\" \u26a0\ufe0f Models disagree significantly!\")" ] }, { @@ -257,15 +257,15 @@ "# Verify consensus\n", "result = verifier.verify(model_outputs)\n", "\n", - "print(\"📊 Multi-Model Consensus\")\n", + "print(\"\ud83d\udcca Multi-Model Consensus\")\n", "print(\"=\" * 60)\n", "for model, output in model_outputs.items():\n", " print(f\" {model}: {output[:50]}...\")\n", "\n", - "print(f\"\\n🎯 Consensus Score: {result.consensus_score:.2%}\")\n", - "print(f\"✅ Consensus Reached: {result.consensus}\")\n", + "print(f\"\\n\ud83c\udfaf Consensus Score: {result.consensus_score:.2%}\")\n", + "print(f\"\u2705 Consensus Reached: {result.consensus}\")\n", "if result.consensus:\n", - " print(f\"📝 Agreed Answer: {result.canonical_answer}\")" + " print(f\"\ud83d\udcdd Agreed Answer: {result.canonical_answer}\")" ] }, { @@ -283,14 +283,14 @@ "\n", "result = verifier.verify(conflicting_outputs)\n", "\n", - "print(\"📊 Conflicting Outputs\")\n", + "print(\"\ud83d\udcca Conflicting Outputs\")\n", "print(\"=\" * 60)\n", "for model, output in conflicting_outputs.items():\n", " print(f\" {model}: {output}\")\n", "\n", - "print(f\"\\n🎯 Consensus Score: {result.consensus_score:.2%}\")\n", - "print(f\"❌ Consensus Reached: {result.consensus}\")\n", - "print(f\"\\n⚠️ Models disagree! Pairwise drift scores:\")\n", + "print(f\"\\n\ud83c\udfaf Consensus Score: {result.consensus_score:.2%}\")\n", + "print(f\"\u274c Consensus Reached: {result.consensus}\")\n", + "print(f\"\\n\u26a0\ufe0f Models disagree! Pairwise drift scores:\")\n", "for pair, score in result.pairwise_scores.items():\n", " print(f\" {pair}: {score:.3f}\")" ] @@ -313,17 +313,17 @@ "# Verify multiple pairs at once\n", "pairs = [\n", " (\"2 + 2 = 4\", \"Two plus two equals four\"),\n", - " (\"Water boils at 100°C\", \"Water boils at 212°F\"),\n", + " (\"Water boils at 100\u00b0C\", \"Water boils at 212\u00b0F\"),\n", " (\"Python is a programming language\", \"Python is a type of snake\"),\n", "]\n", "\n", "results = verify_batch(pairs)\n", "\n", - "print(\"📊 Batch Verification Results\")\n", + "print(\"\ud83d\udcca Batch Verification Results\")\n", "print(\"=\" * 70)\n", "\n", "for (a, b), score in zip(pairs, results):\n", - " status = \"✅\" if score.drift_score < 0.5 else \"⚠️\"\n", + " status = \"\u2705\" if score.drift_score < 0.5 else \"\u26a0\ufe0f\"\n", " print(f\"\\n{status} Drift: {score.drift_score:.3f}\")\n", " print(f\" A: {a}\")\n", " print(f\" B: {b}\")" @@ -381,7 +381,7 @@ "# Execute\n", "result = await kernel.execute(verified_agent, \"What is the speed of light?\")\n", "\n", - "print(\"📊 Verified Agent Result\")\n", + "print(\"\ud83d\udcca Verified Agent Result\")\n", "print(\"=\" * 50)\n", "for k, v in result.items():\n", " print(f\" {k}: {v}\")" @@ -416,13 +416,13 @@ " (\"Water is H2O\", \"Water is composed of hydrogen and oxygen atoms\"),\n", "]\n", "\n", - "print(\"🔍 Hallucination Detection\")\n", + "print(\"\ud83d\udd0d Hallucination Detection\")\n", "print(\"=\" * 70)\n", "\n", "for source, generated in test_cases:\n", " result = detector.check(source_text=source, generated_text=generated)\n", " \n", - " status = \"🚨 HALLUCINATION\" if result.is_hallucination else \"✅ OK\"\n", + " status = \"\ud83d\udea8 HALLUCINATION\" if result.is_hallucination else \"\u2705 OK\"\n", " print(f\"\\n{status}\")\n", " print(f\" Source: {source}\")\n", " print(f\" Generated: {generated}\")\n", @@ -488,4 +488,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} +} \ No newline at end of file diff --git a/packages/agent-os/notebooks/05-multi-agent-coordination.ipynb b/packages/agent-os/notebooks/05-multi-agent-coordination.ipynb index feaa61c7..5fa279a9 100644 --- a/packages/agent-os/notebooks/05-multi-agent-coordination.ipynb +++ b/packages/agent-os/notebooks/05-multi-agent-coordination.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 🤝 Multi-Agent Coordination\n", + "# \ud83e\udd1d Multi-Agent Coordination\n", "\n", "> **Build trust and coordinate between agents using IATP.**\n", "\n", @@ -34,12 +34,12 @@ "Without Trust Protocol: With IATP:\n", "\n", " Agent A Agent A\n", - " ↓ ↓\n", + " \u2193 \u2193\n", " \"Do X\" (unsigned) \"Do X\" + signature\n", - " ↓ ↓\n", + " \u2193 \u2193\n", " Agent B Agent B\n", - " ↓ ↓\n", - " Trust it? 🤷 Verify signature ✓\n", + " \u2193 \u2193\n", + " Trust it? \ud83e\udd37 Verify signature \u2713\n", "```\n", "\n", "---" @@ -58,7 +58,7 @@ "metadata": {}, "outputs": [], "source": [ - "!pip install agent-os[iatp] --quiet" + "!pip install -e ..[iatp] --quiet" ] }, { @@ -89,7 +89,7 @@ " capabilities=[\"code_generation\", \"testing\"]\n", ")\n", "\n", - "print(\"🆔 Agent Identities Created\")\n", + "print(\"\ud83c\udd94 Agent Identities Created\")\n", "print(\"=\" * 50)\n", "print(f\"\\nAlice:\")\n", "print(f\" ID: {alice.agent_id}\")\n", @@ -128,7 +128,7 @@ " }\n", ")\n", "\n", - "print(\"✉️ Signed Message Created\")\n", + "print(\"\u2709\ufe0f Signed Message Created\")\n", "print(\"=\" * 50)\n", "print(f\"From: {message.sender_id}\")\n", "print(f\"To: {message.recipient_id}\")\n", @@ -157,14 +157,14 @@ "# Verify the message\n", "verification = registry.verify(message)\n", "\n", - "print(\"🔍 Message Verification\")\n", + "print(\"\ud83d\udd0d Message Verification\")\n", "print(\"=\" * 50)\n", "print(f\"Valid Signature: {verification.is_valid}\")\n", "print(f\"Sender Verified: {verification.sender_verified}\")\n", "print(f\"Timestamp Valid: {verification.timestamp_valid}\")\n", "\n", "if verification.is_valid:\n", - " print(f\"\\n✅ Bob can trust this message came from Alice!\")" + " print(f\"\\n\u2705 Bob can trust this message came from Alice!\")" ] }, { @@ -179,10 +179,10 @@ "\n", "verification = registry.verify(tampered)\n", "\n", - "print(\"🔍 Tampered Message Verification\")\n", + "print(\"\ud83d\udd0d Tampered Message Verification\")\n", "print(\"=\" * 50)\n", "print(f\"Valid Signature: {verification.is_valid}\")\n", - "print(f\"\\n🚨 Tampering detected! Signature doesn't match content.\")" + "print(f\"\\n\ud83d\udea8 Tampering detected! Signature doesn't match content.\")" ] }, { @@ -215,11 +215,11 @@ ")\n", "registry.register(mallory, trust_level=TrustLevel.NONE)\n", "\n", - "print(\"🏛️ Trust Registry\")\n", + "print(\"\ud83c\udfdb\ufe0f Trust Registry\")\n", "print(\"=\" * 50)\n", "for agent_id, info in registry.list_agents().items():\n", " trust = info['trust_level']\n", - " emoji = \"🟢\" if trust == TrustLevel.HIGH else \"🟡\" if trust == TrustLevel.MEDIUM else \"🔴\"\n", + " emoji = \"\ud83d\udfe2\" if trust == TrustLevel.HIGH else \"\ud83d\udfe1\" if trust == TrustLevel.MEDIUM else \"\ud83d\udd34\"\n", " print(f\"{emoji} {agent_id}: {trust.name}\")" ] }, @@ -233,10 +233,10 @@ "can_alice_to_bob = registry.can_communicate(\"alice-001\", \"bob-001\")\n", "can_mallory_to_alice = registry.can_communicate(\"mallory-001\", \"alice-001\")\n", "\n", - "print(\"🔗 Communication Permissions\")\n", + "print(\"\ud83d\udd17 Communication Permissions\")\n", "print(\"=\" * 50)\n", - "print(f\"Alice → Bob: {'✅ Allowed' if can_alice_to_bob else '❌ Denied'}\")\n", - "print(f\"Mallory → Alice: {'✅ Allowed' if can_mallory_to_alice else '❌ Denied'}\")" + "print(f\"Alice \u2192 Bob: {'\u2705 Allowed' if can_alice_to_bob else '\u274c Denied'}\")\n", + "print(f\"Mallory \u2192 Alice: {'\u2705 Allowed' if can_mallory_to_alice else '\u274c Denied'}\")" ] }, { @@ -316,7 +316,7 @@ "# Execute coordinator\n", "result = await kernel.execute(coordinator_agent, \"Analyze sales data and train predictor\")\n", "\n", - "print(\"🎯 Coordinator Result\")\n", + "print(\"\ud83c\udfaf Coordinator Result\")\n", "print(\"=\" * 50)\n", "for k, v in result.items():\n", " print(f\" {k}: {v}\")" @@ -336,13 +336,13 @@ "outputs": [], "source": [ "# Simulate a compromised agent\n", - "print(\"🔐 Before Revocation:\")\n", + "print(\"\ud83d\udd10 Before Revocation:\")\n", "print(f\" Worker-1 trust: {registry.get_trust_level('worker-1').name}\")\n", "\n", "# Revoke trust\n", "registry.revoke(\"worker-1\", reason=\"Suspicious activity detected\")\n", "\n", - "print(f\"\\n🚨 After Revocation:\")\n", + "print(f\"\\n\ud83d\udea8 After Revocation:\")\n", "print(f\" Worker-1 trust: {registry.get_trust_level('worker-1').name}\")\n", "\n", "# Try to send message from revoked agent\n", @@ -353,7 +353,7 @@ ")\n", "\n", "verification = registry.verify(suspicious_msg)\n", - "print(f\"\\n🔍 Message from revoked agent:\")\n", + "print(f\"\\n\ud83d\udd0d Message from revoked agent:\")\n", "print(f\" Valid: {verification.is_valid}\")\n", "print(f\" Reason: {verification.rejection_reason}\")" ] @@ -385,9 +385,9 @@ "async def handle_task(message: SignedMessage):\n", " # Verify before processing\n", " if registry.verify(message).is_valid:\n", - " print(f\" ✅ Processing: {message.content}\")\n", + " print(f\" \u2705 Processing: {message.content}\")\n", " else:\n", - " print(f\" ❌ Rejected: Invalid signature\")\n", + " print(f\" \u274c Rejected: Invalid signature\")\n", "\n", "bus.subscribe(tasks_topic, handle_task)\n", "\n", @@ -398,7 +398,7 @@ " content={\"action\": \"analyze\", \"data\": \"quarterly_report.csv\"}\n", ")\n", "\n", - "print(\"📬 Publishing signed task to message bus...\")\n", + "print(\"\ud83d\udcec Publishing signed task to message bus...\")\n", "await bus.publish(tasks_topic, task_msg)" ] }, @@ -462,4 +462,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} +} \ No newline at end of file diff --git a/packages/agent-os/notebooks/06-policy-engine.ipynb b/packages/agent-os/notebooks/06-policy-engine.ipynb index 9cf9fdec..aaeaf858 100644 --- a/packages/agent-os/notebooks/06-policy-engine.ipynb +++ b/packages/agent-os/notebooks/06-policy-engine.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 🛡️ Policy Engine Deep Dive\n", + "# \ud83d\udee1\ufe0f Policy Engine Deep Dive\n", "\n", "> **Master kernel policies, signals, and enforcement.**\n", "\n", @@ -30,13 +30,13 @@ "Prompt-Based Safety: Kernel-Based Safety:\n", "\n", " \"Please don't do X\" Every action is checked\n", - " ↓ ↓\n", + " \u2193 \u2193\n", " LLM decides to comply Kernel decides to allow\n", - " ↓ ↓\n", - " Maybe it doesn't 🤷 No choice - blocked or allowed\n", + " \u2193 \u2193\n", + " Maybe it doesn't \ud83e\udd37 No choice - blocked or allowed\n", "```\n", "\n", - "**The kernel doesn't ask the agent to behave—it enforces behavior.**\n", + "**The kernel doesn't ask the agent to behave\u2014it enforces behavior.**\n", "\n", "---" ] @@ -54,7 +54,7 @@ "metadata": {}, "outputs": [], "source": [ - "!pip install agent-os --quiet" + "!pip install -e ../.. --quiet" ] }, { @@ -76,10 +76,10 @@ "# List available templates\n", "templates = PolicyTemplate.list_available()\n", "\n", - "print(\"📋 Available Policy Templates\")\n", + "print(\"\ud83d\udccb Available Policy Templates\")\n", "print(\"=\" * 60)\n", "for name, description in templates.items():\n", - " print(f\"\\n 📁 {name}\")\n", + " print(f\"\\n \ud83d\udcc1 {name}\")\n", " print(f\" {description}\")" ] }, @@ -94,7 +94,7 @@ "permissive_kernel = KernelSpace(policy=\"permissive\")\n", "audit_kernel = KernelSpace(policy=\"audit\")\n", "\n", - "print(\"🛡️ Policy Comparison\")\n", + "print(\"\ud83d\udee1\ufe0f Policy Comparison\")\n", "print(\"=\" * 60)\n", "\n", "for name, kernel in [(\"strict\", strict_kernel), (\"permissive\", permissive_kernel), (\"audit\", audit_kernel)]:\n", @@ -153,7 +153,7 @@ " on_violation=\"SIGKILL\",\n", ")\n", "\n", - "print(\"✅ Custom Policy Created\")\n", + "print(\"\u2705 Custom Policy Created\")\n", "print(f\" Name: {analyst_policy.name}\")\n", "print(f\" Allowed: {analyst_policy.allowed_actions}\")\n", "print(f\" Blocked: {analyst_policy.blocked_actions}\")\n", @@ -175,7 +175,7 @@ "\n", "# This should work\n", "result = await kernel.execute(data_agent, \"Show Q4 revenue trends\")\n", - "print(f\"✅ Allowed: {result}\")" + "print(f\"\u2705 Allowed: {result}\")" ] }, { @@ -236,10 +236,10 @@ " on_violation=\"SIGSTOP\" # Pause instead of kill\n", ")\n", "\n", - "print(\"📋 Advanced Policy with Rules\")\n", + "print(\"\ud83d\udccb Advanced Policy with Rules\")\n", "print(\"=\" * 60)\n", "for rule in advanced_policy.rules:\n", - " print(f\"\\n 📌 {rule.name}\")\n", + " print(f\"\\n \ud83d\udccc {rule.name}\")\n", " print(f\" Action: {rule.action}\")\n", " print(f\" Message: {rule.message}\")" ] @@ -265,7 +265,7 @@ "@kernel.on_signal(AgentSignal.SIGKILL)\n", "async def handle_kill(agent_id: str, context: dict):\n", " \"\"\"Called when an agent is terminated.\"\"\"\n", - " print(f\"🚨 SIGKILL received for {agent_id}\")\n", + " print(f\"\ud83d\udea8 SIGKILL received for {agent_id}\")\n", " print(f\" Reason: {context.get('reason', 'Unknown')}\")\n", " print(f\" Action: {context.get('action', 'Unknown')}\")\n", " # Log to audit system, send alerts, etc.\n", @@ -273,17 +273,17 @@ "@kernel.on_signal(AgentSignal.SIGSTOP)\n", "async def handle_stop(agent_id: str, context: dict):\n", " \"\"\"Called when an agent is paused.\"\"\"\n", - " print(f\"⏸️ SIGSTOP received for {agent_id}\")\n", + " print(f\"\u23f8\ufe0f SIGSTOP received for {agent_id}\")\n", " print(f\" Reason: {context.get('reason', 'Unknown')}\")\n", " # Queue for human review\n", "\n", "@kernel.on_signal(AgentSignal.SIGCONT)\n", "async def handle_continue(agent_id: str, context: dict):\n", " \"\"\"Called when an agent is resumed.\"\"\"\n", - " print(f\"▶️ SIGCONT received for {agent_id}\")\n", + " print(f\"\u25b6\ufe0f SIGCONT received for {agent_id}\")\n", " print(f\" Approved by: {context.get('approved_by', 'System')}\")\n", "\n", - "print(\"✅ Signal handlers registered\")\n", + "print(\"\u2705 Signal handlers registered\")\n", "print(f\" SIGKILL: handle_kill\")\n", "print(f\" SIGSTOP: handle_stop\")\n", "print(f\" SIGCONT: handle_continue\")" @@ -305,7 +305,7 @@ "try:\n", " await kernel.execute(bad_agent, \"Clean up files\")\n", "except Exception as e:\n", - " print(f\"\\n❌ Agent terminated: {e}\")" + " print(f\"\\n\u274c Agent terminated: {e}\")" ] }, { @@ -369,7 +369,7 @@ "with open(\"security.yaml\", \"w\") as f:\n", " f.write(policy_yaml)\n", "\n", - "print(\"📝 Policy file created: security.yaml\")" + "print(\"\ud83d\udcdd Policy file created: security.yaml\")" ] }, { @@ -381,7 +381,7 @@ "# Load policy from file\n", "kernel = KernelSpace(policy_file=\"security.yaml\")\n", "\n", - "print(\"✅ Policy loaded from security.yaml\")\n", + "print(\"\u2705 Policy loaded from security.yaml\")\n", "print(f\" Mode: {kernel.policy.mode}\")\n", "print(f\" Policies: {len(kernel.policy.policies)}\")\n", "print(f\" Audit: {kernel.policy.audit_enabled}\")" @@ -412,12 +412,12 @@ " {\"action\": \"query_database\", \"query\": \"SELECT ssn FROM users\"},\n", "]\n", "\n", - "print(\"🔍 Policy Debugging\")\n", + "print(\"\ud83d\udd0d Policy Debugging\")\n", "print(\"=\" * 70)\n", "\n", "for test in test_cases:\n", " result = debugger.evaluate(test)\n", - " status = \"✅ ALLOW\" if result.allowed else \"❌ BLOCK\"\n", + " status = \"\u2705 ALLOW\" if result.allowed else \"\u274c BLOCK\"\n", " print(f\"\\n{status}: {test['action']}\")\n", " if not result.allowed:\n", " print(f\" Rule: {result.triggered_rule}\")\n", @@ -455,7 +455,7 @@ "# View audit log\n", "audit = kernel.get_audit_log()\n", "\n", - "print(\"📜 Audit Trail\")\n", + "print(\"\ud83d\udcdc Audit Trail\")\n", "print(\"=\" * 70)\n", "for entry in audit.entries:\n", " print(f\"\\n {entry.timestamp}\")\n", @@ -483,7 +483,7 @@ "for f in [\"security.yaml\", \"audit.log\"]:\n", " if os.path.exists(f):\n", " os.remove(f)\n", - " print(f\"🗑️ Removed {f}\")" + " print(f\"\ud83d\uddd1\ufe0f Removed {f}\")" ] }, { @@ -553,4 +553,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} +} \ No newline at end of file From 7a3fdb988346424acf435d03885863fa7e18c0ee Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Sat, 21 Mar 2026 09:25:52 -0700 Subject: [PATCH 08/12] =?UTF-8?q?fix(security):=20complete=20dependency=20?= =?UTF-8?q?confusion=20fix=20=E2=80=94=20replace=20all=20pip=20install=20a?= =?UTF-8?q?gent-os=20with=20agent-os-kernel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace all remaining instances of `pip install agent-os` (unregistered on PyPI) with `pip install agent-os-kernel` (the actual package) across docs, examples, TypeScript extensions, CLI source, tests, and SVG assets. Also fixes `pip install emk` references to point to `agent-os-kernel[full]` since emk is a submodule, not a standalone PyPI package. Completes the fix started in PR #325 which only covered notebooks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/deployment/azure-foundry-agent-service.md | 2 +- docs/tutorials/06-execution-sandboxing.md | 2 +- .../submissions/adversa-mcp-security-submission.md | 2 +- .../submissions/owasp-genai-implementation-guide.md | 4 ++-- packages/agent-os/assets/demo-terminal.svg | 2 +- packages/agent-os/docs/index.md | 2 +- packages/agent-os/docs/troubleshooting.md | 2 +- packages/agent-os/docs/tutorials/getting-started.md | 2 +- packages/agent-os/docs/tutorials/vscode-extension.md | 2 +- packages/agent-os/docs/unified-vision.md | 2 +- .../examples/crewai-safe-mode/crewai_safe_mode.py | 2 +- .../examples/crewai-safe-mode/langchain_safe_mode.py | 2 +- packages/agent-os/examples/hello-world/README.md | 2 +- .../examples/integrations/governance_quickstart.py | 2 +- .../agent-os/extensions/copilot/src/agentGenerator.ts | 2 +- .../extensions/copilot/src/githubIntegration.ts | 8 ++++---- .../src/enterprise/integration/cicdIntegration.ts | 10 +++++----- packages/agent-os/modules/emk/README.md | 2 +- packages/agent-os/modules/emk/emk/hf_utils.py | 4 ++-- packages/agent-os/src/agent_os/cli/__init__.py | 2 +- packages/agent-os/tests/test_cli.py | 2 +- .../copilot-governance/README.md | 2 +- .../copilot-governance/src/reviewer.ts | 2 +- 23 files changed, 32 insertions(+), 32 deletions(-) diff --git a/docs/deployment/azure-foundry-agent-service.md b/docs/deployment/azure-foundry-agent-service.md index 5643c4c8..e4bad904 100644 --- a/docs/deployment/azure-foundry-agent-service.md +++ b/docs/deployment/azure-foundry-agent-service.md @@ -82,7 +82,7 @@ Each middleware works independently. Use any combination based on your requireme pip install agent-governance-toolkit[full] # Or install individual packages -pip install agent-os agentmesh agent-sre +pip install agent-os-kernel agentmesh-platform agent-sre ``` --- diff --git a/docs/tutorials/06-execution-sandboxing.md b/docs/tutorials/06-execution-sandboxing.md index fa3495ae..fc693086 100644 --- a/docs/tutorials/06-execution-sandboxing.md +++ b/docs/tutorials/06-execution-sandboxing.md @@ -55,7 +55,7 @@ layers of defense: - Python ≥ 3.11 - `pip install agent-runtime` (v2.0.2+) -- For capability guards: `pip install agent-os` +- For capability guards: `pip install agent-os-kernel` --- diff --git a/packages/agent-compliance/docs/submissions/adversa-mcp-security-submission.md b/packages/agent-compliance/docs/submissions/adversa-mcp-security-submission.md index fb2cca2e..594a8b5a 100644 --- a/packages/agent-compliance/docs/submissions/adversa-mcp-security-submission.md +++ b/packages/agent-compliance/docs/submissions/adversa-mcp-security-submission.md @@ -88,7 +88,7 @@ Identifies malicious schema patterns: ```bash # Install -pip install agent-os +pip install agent-os-kernel # Scan an MCP configuration file mcp-scan scan mcp-config.json diff --git a/packages/agent-compliance/docs/submissions/owasp-genai-implementation-guide.md b/packages/agent-compliance/docs/submissions/owasp-genai-implementation-guide.md index 3152de70..b7ca868e 100644 --- a/packages/agent-compliance/docs/submissions/owasp-genai-implementation-guide.md +++ b/packages/agent-compliance/docs/submissions/owasp-genai-implementation-guide.md @@ -11,7 +11,7 @@ The stack consists of four components: | Component | Role | Install | |---|---|---| -| **Agent OS** | Governance kernel — policy, sandbox, memory, MCP security | `pip install agent-os` | +| **Agent OS** | Governance kernel — policy, sandbox, memory, MCP security | `pip install agent-os-kernel` | | **AgentMesh** | Identity & trust — DIDs, SPIFFE, handshake, reputation | `pip install agentmesh` | | **Agent SRE** | Observability — SLOs, anomaly detection, chaos, OpenTelemetry | `pip install agent-sre` | | **Agent Runtime** | Runtime control — kill switch, execution rings, saga rollback | `pip install agent-runtime` | @@ -1044,7 +1044,7 @@ This implementation guide is a community contribution to the OWASP GenAI project To reproduce the examples, install the stack: ```bash -pip install agent-os agentmesh agent-sre agent-runtime +pip install agent-os-kernel agentmesh-platform agent-sre agent-runtime ``` All source code is available under the MIT license. PRs and issues welcome at diff --git a/packages/agent-os/assets/demo-terminal.svg b/packages/agent-os/assets/demo-terminal.svg index b874ea51..d44f9d98 100644 --- a/packages/agent-os/assets/demo-terminal.svg +++ b/packages/agent-os/assets/demo-terminal.svg @@ -43,7 +43,7 @@ - $ pip install agent-os + $ pip install agent-os-kernel diff --git a/packages/agent-os/docs/index.md b/packages/agent-os/docs/index.md index 50104891..8fd5b4c3 100644 --- a/packages/agent-os/docs/index.md +++ b/packages/agent-os/docs/index.md @@ -59,7 +59,7 @@ Learn by doing with our Jupyter notebooks: ```bash # Core package -pip install agent-os +pip install agent-os-kernel # With all features pip install agent-os-kernel[full] diff --git a/packages/agent-os/docs/troubleshooting.md b/packages/agent-os/docs/troubleshooting.md index 089bc7f5..c289c9cb 100644 --- a/packages/agent-os/docs/troubleshooting.md +++ b/packages/agent-os/docs/troubleshooting.md @@ -43,7 +43,7 @@ Common issues and solutions for Agent OS. 2. **Install in the correct environment:** ```bash - python -m pip install agent-os + python -m pip install agent-os-kernel ``` ### Import errors with optional dependencies diff --git a/packages/agent-os/docs/tutorials/getting-started.md b/packages/agent-os/docs/tutorials/getting-started.md index 61628f58..8132d8b9 100644 --- a/packages/agent-os/docs/tutorials/getting-started.md +++ b/packages/agent-os/docs/tutorials/getting-started.md @@ -10,7 +10,7 @@ ## Step 1: Install (30 seconds) ```bash -pip install agent-os +pip install agent-os-kernel ``` ## Step 2: Create Your First Agent (2 minutes) diff --git a/packages/agent-os/docs/tutorials/vscode-extension.md b/packages/agent-os/docs/tutorials/vscode-extension.md index 51299e07..b2657218 100644 --- a/packages/agent-os/docs/tutorials/vscode-extension.md +++ b/packages/agent-os/docs/tutorials/vscode-extension.md @@ -509,7 +509,7 @@ jobs: python-version: '3.11' - name: Install AgentOS - run: pip install agent-os + run: pip install agent-os-kernel - name: Run Policy Validation run: agent-os validate --policy policies/ --strict diff --git a/packages/agent-os/docs/unified-vision.md b/packages/agent-os/docs/unified-vision.md index 866dd10f..f49fe8e6 100644 --- a/packages/agent-os/docs/unified-vision.md +++ b/packages/agent-os/docs/unified-vision.md @@ -336,7 +336,7 @@ spec: ### Step 1: Start with Agent OS ```bash -pip install agent-os +pip install agent-os-kernel ``` ```python diff --git a/packages/agent-os/examples/crewai-safe-mode/crewai_safe_mode.py b/packages/agent-os/examples/crewai-safe-mode/crewai_safe_mode.py index 4fe77b77..cf830bad 100644 --- a/packages/agent-os/examples/crewai-safe-mode/crewai_safe_mode.py +++ b/packages/agent-os/examples/crewai-safe-mode/crewai_safe_mode.py @@ -15,7 +15,7 @@ 4. Your data stays safe ✓ Run: - pip install agent-os crewai + pip install agent-os-kernel crewai python crewai_safe_mode.py Perfect for recording a 15-second GIF showing "Access Denied"! diff --git a/packages/agent-os/examples/crewai-safe-mode/langchain_safe_mode.py b/packages/agent-os/examples/crewai-safe-mode/langchain_safe_mode.py index d098ffb4..6e824b10 100644 --- a/packages/agent-os/examples/crewai-safe-mode/langchain_safe_mode.py +++ b/packages/agent-os/examples/crewai-safe-mode/langchain_safe_mode.py @@ -15,7 +15,7 @@ 4. Your data stays safe ✓ Run: - pip install agent-os langchain + pip install agent-os-kernel langchain python langchain_safe_mode.py For PyPI package: pip install langchain-agent-os diff --git a/packages/agent-os/examples/hello-world/README.md b/packages/agent-os/examples/hello-world/README.md index 9b61435e..cc660501 100644 --- a/packages/agent-os/examples/hello-world/README.md +++ b/packages/agent-os/examples/hello-world/README.md @@ -12,7 +12,7 @@ The simplest possible Agent OS example. ```bash # Install -pip install agent-os +pip install agent-os-kernel # Run python agent.py diff --git a/packages/agent-os/examples/integrations/governance_quickstart.py b/packages/agent-os/examples/integrations/governance_quickstart.py index d2131020..35c687b4 100644 --- a/packages/agent-os/examples/integrations/governance_quickstart.py +++ b/packages/agent-os/examples/integrations/governance_quickstart.py @@ -7,7 +7,7 @@ audit trails) to every major agent framework with a unified API. Usage: - pip install agent-os + pip install agent-os-kernel python governance_quickstart.py """ diff --git a/packages/agent-os/extensions/copilot/src/agentGenerator.ts b/packages/agent-os/extensions/copilot/src/agentGenerator.ts index aeca3651..f0a2b70f 100644 --- a/packages/agent-os/extensions/copilot/src/agentGenerator.ts +++ b/packages/agent-os/extensions/copilot/src/agentGenerator.ts @@ -687,7 +687,7 @@ jobs: - name: Install dependencies run: | - pip install agent-os + pip install agent-os-kernel pip install -r requirements.txt - name: Run Agent diff --git a/packages/agent-os/extensions/copilot/src/githubIntegration.ts b/packages/agent-os/extensions/copilot/src/githubIntegration.ts index 50a4093a..3c3325b2 100644 --- a/packages/agent-os/extensions/copilot/src/githubIntegration.ts +++ b/packages/agent-os/extensions/copilot/src/githubIntegration.ts @@ -199,7 +199,7 @@ jobs: - name: Install Agent OS run: | - pip install agent-os + pip install agent-os-kernel pip install -r requirements.txt || true - name: Validate policies @@ -270,7 +270,7 @@ jobs: python-version: '3.11' - name: Run tests run: | - pip install agent-os pytest + pip install agent-os-kernel pytest pytest tests/test_${this.toSnakeCase(spec.name)}.py -v security-scan: @@ -279,7 +279,7 @@ jobs: - uses: actions/checkout@v4 - name: Security scan run: | - pip install agent-os + pip install agent-os-kernel agentos check agents/${this.toSnakeCase(spec.name)}.py --security deploy-staging: @@ -465,7 +465,7 @@ gh workflow run ${this.toKebabCase(spec.name)}.yml ### Local Development \`\`\`bash # Install dependencies -pip install agent-os +pip install agent-os-kernel # Run locally python agents/${this.toSnakeCase(spec.name)}.py diff --git a/packages/agent-os/extensions/vscode/src/enterprise/integration/cicdIntegration.ts b/packages/agent-os/extensions/vscode/src/enterprise/integration/cicdIntegration.ts index 74b53c03..9a84fa7f 100644 --- a/packages/agent-os/extensions/vscode/src/enterprise/integration/cicdIntegration.ts +++ b/packages/agent-os/extensions/vscode/src/enterprise/integration/cicdIntegration.ts @@ -61,7 +61,7 @@ jobs: python-version: '3.11' - name: Install Agent OS - run: pip install agent-os + run: pip install agent-os-kernel - name: Run Policy Validation run: | @@ -89,7 +89,7 @@ agent-os-check: stage: security image: python:3.11 before_script: - - pip install agent-os + - pip install agent-os-kernel script: - agentos check --format json --output agent-os-report.json - agentos check --fail-on-violation @@ -119,7 +119,7 @@ steps: versionSpec: '3.11' - script: | - pip install agent-os + pip install agent-os-kernel displayName: 'Install Agent OS' - script: | @@ -147,7 +147,7 @@ steps: stages { stage('Setup') { steps { - sh 'pip install agent-os' + sh 'pip install agent-os-kernel' } } @@ -189,7 +189,7 @@ jobs: - checkout - run: name: Install Agent OS - command: pip install agent-os + command: pip install agent-os-kernel - run: name: Run Security Check command: | diff --git a/packages/agent-os/modules/emk/README.md b/packages/agent-os/modules/emk/README.md index b3269f81..476a155f 100644 --- a/packages/agent-os/modules/emk/README.md +++ b/packages/agent-os/modules/emk/README.md @@ -12,7 +12,7 @@ emk provides a simple append-only store for recording agent experiences. Episode ## Installation ```bash -pip install emk +pip install agent-os-kernel[full] # emk is included as a submodule ``` ## Quick Start diff --git a/packages/agent-os/modules/emk/emk/hf_utils.py b/packages/agent-os/modules/emk/emk/hf_utils.py index 8ee40c06..919aacc5 100644 --- a/packages/agent-os/modules/emk/emk/hf_utils.py +++ b/packages/agent-os/modules/emk/emk/hf_utils.py @@ -7,7 +7,7 @@ results to/from the Hugging Face Hub for sharing and reproducibility. Requirements: - pip install emk[huggingface] + pip install agent-os-kernel[full] # includes emk with huggingface support Example: >>> from emk.hf_utils import upload_episodes_to_hub @@ -52,7 +52,7 @@ def _check_hf_hub() -> None: if not _HF_HUB_AVAILABLE: raise ImportError( "huggingface_hub is required for this functionality. " - "Install it with: pip install emk[huggingface]" + "Install it with: pip install agent-os-kernel[full]" ) diff --git a/packages/agent-os/src/agent_os/cli/__init__.py b/packages/agent-os/src/agent_os/cli/__init__.py index 5df05d5e..53be79b9 100644 --- a/packages/agent-os/src/agent_os/cli/__init__.py +++ b/packages/agent-os/src/agent_os/cli/__init__.py @@ -202,7 +202,7 @@ def handle_invalid_policy(name: str) -> str: def handle_missing_dependency(package: str, extra: str = "") -> str: """Error message when an optional dependency is missing.""" - install_cmd = f"pip install agent-os[{extra}]" if extra else f"pip install {package}" + install_cmd = f"pip install agent-os-kernel[{extra}]" if extra else f"pip install {package}" return format_error( f"Required package not installed: {package}", suggestion=f"Install with: {install_cmd}", diff --git a/packages/agent-os/tests/test_cli.py b/packages/agent-os/tests/test_cli.py index 68ffbbb3..215fea70 100644 --- a/packages/agent-os/tests/test_cli.py +++ b/packages/agent-os/tests/test_cli.py @@ -524,7 +524,7 @@ def test_handle_missing_dependency(self): from agent_os.cli import handle_missing_dependency msg = handle_missing_dependency("redis", extra="redis") - assert "pip install agent-os[redis]" in msg + assert "pip install agent-os-kernel[redis]" in msg def test_handle_connection_error(self): """Test connection-error helper includes host:port.""" diff --git a/packages/agentmesh-integrations/copilot-governance/README.md b/packages/agentmesh-integrations/copilot-governance/README.md index 74b1d709..f2cebecc 100644 --- a/packages/agentmesh-integrations/copilot-governance/README.md +++ b/packages/agentmesh-integrations/copilot-governance/README.md @@ -197,7 +197,7 @@ npm install @agentmesh/mastra **Python agents:** ```bash -pip install agent-os +pip install agent-os-kernel ``` See the [Agent Governance Toolkit](https://github.com/microsoft/agent-governance-toolkit) for the full documentation. diff --git a/packages/agentmesh-integrations/copilot-governance/src/reviewer.ts b/packages/agentmesh-integrations/copilot-governance/src/reviewer.ts index 82ddc854..9f0dc197 100644 --- a/packages/agentmesh-integrations/copilot-governance/src/reviewer.ts +++ b/packages/agentmesh-integrations/copilot-governance/src/reviewer.ts @@ -563,7 +563,7 @@ export function formatReviewResult(result: ReviewResult): string { lines.push( "> 📦 Add governance to your agent in minutes: " + "`npm install @agentmesh/mastra` (TypeScript) or " + - "`pip install agent-os` (Python)." + "`pip install agent-os-kernel` (Python)." ); return lines.join("\n"); From 58bc4fd909d2cfc47d2415c256f8270f3379923e Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Sat, 21 Mar 2026 09:57:12 -0700 Subject: [PATCH 09/12] docs: update framework star counts to current values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dify 65K→133K, AutoGen 42K→55K, CrewAI 28K→46K, Semantic Kernel 24K→27K, LangGraph 24K→27K, Haystack 22K→24K, Agent Framework 7.6K→8K. Added star counts for OpenAI Agents SDK (20K) and Google ADK (18K). Sorted by stars descending. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0e10d718..c7a95825 100644 --- a/README.md +++ b/README.md @@ -244,17 +244,17 @@ Works with **12+ agent frameworks** including: | Framework | Stars | Integration | |-----------|-------|-------------| -| [**Microsoft Agent Framework**](https://github.com/microsoft/agent-framework) | 7.6K+ ⭐ | **Native Middleware** | -| [**Semantic Kernel**](https://github.com/microsoft/semantic-kernel) | 24K+ ⭐ | **Native (.NET + Python)** | -| [Dify](https://github.com/langgenius/dify) | 65K+ ⭐ | Plugin | +| [**Microsoft Agent Framework**](https://github.com/microsoft/agent-framework) | 8K+ ⭐ | **Native Middleware** | +| [**Semantic Kernel**](https://github.com/microsoft/semantic-kernel) | 27K+ ⭐ | **Native (.NET + Python)** | +| [Dify](https://github.com/langgenius/dify) | 133K+ ⭐ | Plugin | +| [Microsoft AutoGen](https://github.com/microsoft/autogen) | 55K+ ⭐ | Adapter | | [LlamaIndex](https://github.com/run-llama/llama_index) | 47K+ ⭐ | Middleware | -| [LangGraph](https://github.com/langchain-ai/langgraph) | 24K+ ⭐ | Adapter | -| [Microsoft AutoGen](https://github.com/microsoft/autogen) | 42K+ ⭐ | Adapter | -| [CrewAI](https://github.com/crewAIInc/crewAI) | 28K+ ⭐ | Adapter | +| [CrewAI](https://github.com/crewAIInc/crewAI) | 46K+ ⭐ | Adapter | +| [LangGraph](https://github.com/langchain-ai/langgraph) | 27K+ ⭐ | Adapter | +| [Haystack](https://github.com/deepset-ai/haystack) | 24K+ ⭐ | Pipeline | +| [OpenAI Agents SDK](https://github.com/openai/openai-agents-python) | 20K+ ⭐ | Middleware | +| [Google ADK](https://github.com/google/adk-python) | 18K+ ⭐ | Adapter | | [Azure AI Foundry](https://learn.microsoft.com/azure/ai-studio/) | — | Deployment Guide | -| [OpenAI Agents SDK](https://github.com/openai/openai-agents-python) | — | Middleware | -| [Google ADK](https://github.com/google/adk-python) | — | Adapter | -| [Haystack](https://github.com/deepset-ai/haystack) | 22K+ ⭐ | Pipeline | ## OWASP Agentic Top 10 Coverage From 18aa2889cdcb9fb272887b40dcfe4148398357cc Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Mon, 23 Mar 2026 11:41:50 -0700 Subject: [PATCH 10/12] feat(security): add dependency confusion pre-commit hook + weekly audit CI - scripts/check_dependency_confusion.py: Pre-commit hook that scans for pip install commands referencing unregistered PyPI packages. Maintains an allowlist of known registered packages. - .github/workflows/weekly-security-audit.yml: Weekly CI job running dependency confusion scan, security skills scan, and weak crypto check. Uploads reports as artifacts with 90-day retention. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/weekly-security-audit.yml | 112 +++++++++++++++++ scripts/check_dependency_confusion.py | 131 ++++++++++++++++++++ 2 files changed, 243 insertions(+) create mode 100644 .github/workflows/weekly-security-audit.yml create mode 100644 scripts/check_dependency_confusion.py diff --git a/.github/workflows/weekly-security-audit.yml b/.github/workflows/weekly-security-audit.yml new file mode 100644 index 00000000..c7f9a775 --- /dev/null +++ b/.github/workflows/weekly-security-audit.yml @@ -0,0 +1,112 @@ +name: Weekly Security Audit + +on: + schedule: + - cron: "0 8 * * 1" # Monday 8:00 UTC + workflow_dispatch: + +permissions: + contents: read + issues: write + +jobs: + dependency-confusion-check: + name: Dependency Confusion Scan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: "3.11" + + - name: Scan for unregistered pip install targets + id: dep-check + run: | + # Find all pip install commands and check package names + python scripts/check_dependency_confusion.py \ + $(find . -name "*.md" -o -name "*.py" -o -name "*.ts" -o -name "*.txt" -o -name "*.yaml" -o -name "*.svg" -o -name "*.ipynb" \ + | grep -v node_modules | grep -v .git | grep -v __pycache__ | grep -v .venv) \ + > dep-confusion-report.txt 2>&1 || true + if [ -s dep-confusion-report.txt ]; then + echo "has-findings=true" >> "$GITHUB_OUTPUT" + echo "### ⚠️ Dependency Confusion Findings" >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + cat dep-confusion-report.txt >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + else + echo "has-findings=false" >> "$GITHUB_OUTPUT" + echo "### ✅ No dependency confusion findings" >> "$GITHUB_STEP_SUMMARY" + fi + + security-skills-scan: + name: Security Skills Scan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: "3.11" + + - name: Install dependencies + run: pip install pyyaml + + - name: Run security skills scan + continue-on-error: true + run: | + python scripts/security_scan.py packages/ \ + --exclude-tests \ + --min-severity high \ + --format text | tee security-report.txt + + - name: Generate JSON report + if: always() + run: | + python scripts/security_scan.py packages/ \ + --exclude-tests \ + --format json > weekly-security-report.json || true + + - name: Upload reports + if: always() + uses: actions/upload-artifact@ea165f8d65b6db9a6b7e75b195db6a6b2be22da8 # v4.6.2 + with: + name: weekly-security-audit + path: | + weekly-security-report.json + dep-confusion-report.txt + retention-days: 90 + + weak-crypto-check: + name: Weak Cryptography Scan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Check for MD5/SHA1 in non-test code + run: | + echo "### Weak Cryptography Check" >> "$GITHUB_STEP_SUMMARY" + FINDINGS=$(grep -rn "hashlib\.md5\|hashlib\.sha1" --include="*.py" packages/ \ + | grep -v "test_" | grep -v "text_tool" | grep -v "security_skills" \ + | grep -v "example" | grep -v "benchmark" | grep -v "red_team" || true) + if [ -n "$FINDINGS" ]; then + echo "⚠️ MD5/SHA1 found in production code:" >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + echo "$FINDINGS" >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + else + echo "✅ No weak cryptography in production code" >> "$GITHUB_STEP_SUMMARY" + fi + + - name: Check for pickle in non-test code + run: | + FINDINGS=$(grep -rn "pickle\.load" --include="*.py" packages/ \ + | grep -v "test_" | grep -v "security_skills" | grep -v "# " || true) + if [ -n "$FINDINGS" ]; then + echo "⚠️ pickle usage found:" >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + echo "$FINDINGS" >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + else + echo "✅ No pickle deserialization in production code" >> "$GITHUB_STEP_SUMMARY" + fi diff --git a/scripts/check_dependency_confusion.py b/scripts/check_dependency_confusion.py new file mode 100644 index 00000000..59cd7b9f --- /dev/null +++ b/scripts/check_dependency_confusion.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +"""Pre-commit hook: detect unregistered PyPI package names in pip install commands. + +Scans staged files for `pip install ` where is not a known +registered package. Prevents dependency confusion attacks. + +Usage: + # Install as pre-commit hook + cp scripts/check_dependency_confusion.py .git/hooks/pre-commit + chmod +x .git/hooks/pre-commit + + # Or run manually + python scripts/check_dependency_confusion.py [files...] +""" + +import re +import subprocess +import sys + +# Known registered PyPI package names for this project +REGISTERED_PACKAGES = { + # Core packages (on PyPI) + "agent-os-kernel", + "agentmesh-platform", + "agent-hypervisor", + "agent-runtime", + "agent-sre", + "agent-governance-toolkit", + "agent-lightning", + "agent-marketplace", + # Common dependencies + "pydantic", "pyyaml", "cryptography", "pynacl", "httpx", "aiohttp", + "fastapi", "uvicorn", "structlog", "click", "rich", "numpy", "scipy", + "pytest", "pytest-asyncio", "pytest-cov", "ruff", "mypy", "build", + "openai", "anthropic", "langchain", "langchain-core", "crewai", + "redis", "sqlalchemy", "asyncpg", "chromadb", "pinecone-client", + "sentence-transformers", "prometheus-client", "opentelemetry-api", + "opentelemetry-sdk", "fhir.resources", "hl7apy", "zenpy", "freshdesk", + "google-adk", "safety", "jupyter", "vitest", "tsup", "typescript", + # With extras (base name is what matters) +} + +# Patterns that are always safe +SAFE_PATTERNS = { + "-e", "--editable", "-r", "--requirement", "--upgrade", "--no-cache-dir", + "--quiet", "--require-hashes", "--hash", ".", "..", "../..", +} + +PIP_INSTALL_RE = re.compile( + r'pip\s+install\s+(.+?)(?:\s*\\?\s*$|(?=\s*&&|\s*\||\s*;|\s*#))', + re.MULTILINE, +) + + +def extract_package_names(install_args: str) -> list[str]: + """Extract package names from a pip install argument string.""" + packages = [] + for token in install_args.split(): + # Skip flags + if token.startswith("-") or token in SAFE_PATTERNS: + continue + if token.startswith((".", "/", "\\", "http", "git+")): + continue + # Strip extras: package[extra] -> package + base = re.sub(r'\[.*\]', '', token) + # Strip version specifiers: package>=1.0 -> package + base = re.split(r'[><=!~]', base)[0] + # Strip markdown/quote artifacts + base = base.strip('`"\'(){}') + if base and base not in SAFE_PATTERNS: + packages.append(base) + return packages + + +def check_file(filepath: str) -> list[str]: + """Check a file for potentially unregistered pip install targets.""" + findings = [] + try: + with open(filepath, encoding="utf-8", errors="ignore") as f: + content = f.read() + except (OSError, UnicodeDecodeError): + return findings + + for match in PIP_INSTALL_RE.finditer(content): + line_num = content[:match.start()].count("\n") + 1 + packages = extract_package_names(match.group(1)) + for pkg in packages: + if pkg.lower() not in {p.lower() for p in REGISTERED_PACKAGES}: + findings.append( + f" {filepath}:{line_num}: " + f"'{pkg}' may not be registered on PyPI" + ) + return findings + + +def main() -> int: + # Get files to check + if len(sys.argv) > 1: + files = sys.argv[1:] + else: + # Pre-commit mode: check staged files + result = subprocess.run( + ["git", "diff", "--cached", "--name-only", "--diff-filter=ACM"], + capture_output=True, text=True, + ) + files = [ + f for f in result.stdout.strip().split("\n") + if f.endswith((".md", ".py", ".ts", ".txt", ".yaml", ".yml", ".ipynb", ".svg")) + ] + + all_findings = [] + for f in files: + all_findings.extend(check_file(f)) + + if all_findings: + print("⚠️ Potential dependency confusion detected:") + print() + for finding in all_findings: + print(finding) + print() + print("If the package IS registered on PyPI, add it to REGISTERED_PACKAGES") + print("in scripts/check_dependency_confusion.py") + return 1 + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 44a2b80d3ea2f3d176c4ab90991159ca323563cc Mon Sep 17 00:00:00 2001 From: Imran Siddique <45405841+imran-siddique@users.noreply.github.com> Date: Mon, 23 Mar 2026 11:38:53 -0700 Subject: [PATCH 11/12] =?UTF-8?q?fix(security):=20proactive=20audit=20?= =?UTF-8?q?=E2=80=94=20dependency=20confusion=20+=20MD5=E2=86=92SHA-256=20?= =?UTF-8?q?(#349)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: add testing guide for external testers and customers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: add regulatory alignment table and Purview positioning to README Add EU AI Act, Colorado AI Act, and GPAI obligations timeline with AGT coverage mapping. Reference Microsoft Purview DSPM for AI as complementary data governance layer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(ci): restore read-all at workflow level for Scorecard verification The Scorecard API rejects workflows with write permissions at the workflow level. id-token: write and security-events: write must be scoped to the job level only. Restores permissions: read-all at workflow level while keeping job-level write permissions intact. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: add comprehensive docstrings to mcp_adapter.py classes (#324) Add Google-style docstrings with Args, Returns, Raises, Attributes, and Example sections to MCPMessageType, MCPAdapter, and MCPServer classes. Also enhances docstrings for key methods including handle_message, _handle_tools_call, _handle_resources_read, and _map_tool_to_action. Fixes #316 * ci: add markdown link checker workflow (#323) Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> * feat: add policy evaluation heatmap to SRE dashboard (#309) (#326) * fix: remove unregistered PyPI packages from notebooks and requirements (dependency confusion) (#325) - Replace !pip install agent-os with !pip install -e ../.. in all 6 notebooks; agent-os is not on PyPI and installing it from PyPI is a dependency confusion vector - Replace zendesk-sdk/freshdesk-sdk with zenpy/freshdesk (the real published SDKs) in customer-service/requirements.txt - Remove hashlib-compat from healthcare-hipaa/requirements.txt; hashlib is stdlib and hashlib-compat is not a real PyPI package * fix(security): complete dependency confusion fix — replace all pip install agent-os with agent-os-kernel Replace all remaining instances of `pip install agent-os` (unregistered on PyPI) with `pip install agent-os-kernel` (the actual package) across docs, examples, TypeScript extensions, CLI source, tests, and SVG assets. Also fixes `pip install emk` references to point to `agent-os-kernel[full]` since emk is a submodule, not a standalone PyPI package. Completes the fix started in PR #325 which only covered notebooks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: update framework star counts to current values Dify 65K→133K, AutoGen 42K→55K, CrewAI 28K→46K, Semantic Kernel 24K→27K, LangGraph 24K→27K, Haystack 22K→24K, Agent Framework 7.6K→8K. Added star counts for OpenAI Agents SDK (20K) and Google ADK (18K). Sorted by stars descending. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Parsa Faraji Alamouti <165321600+parsa-faraji@users.noreply.github.com> Co-authored-by: Matt Van Horn Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: Zeel Desai <72783325+zeel2104@users.noreply.github.com> Co-authored-by: Xavier Garceau-Aranda From 9fad202bc46df97fad57dbd8888a6c44ce0d19c2 Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Mon, 23 Mar 2026 12:54:45 -0700 Subject: [PATCH 12/12] =?UTF-8?q?fix(security):=20replace=20unregistered?= =?UTF-8?q?=20package=20names=20+=20MD5=E2=86=92SHA-256?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - agentmesh → agentmesh-platform (5 files) - agentmesh-governance → agent-governance-toolkit - agent-os-observability → agent-os-kernel[observability] - hashlib.md5 → hashlib.sha256 (3 files) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/integrations/openshell.md | 2 +- .../docs/submissions/owasp-genai-implementation-guide.md | 2 +- packages/agent-mesh/src/agentmesh/cli/main.py | 2 +- packages/agent-mesh/src/agentmesh/transport/grpc_transport.py | 4 ++-- .../control-plane/src/agent_control_plane/lifecycle.py | 4 ++-- .../control-plane/src/agent_control_plane/ml_safety.py | 2 +- .../modules/mcp-kernel-server/src/mcp_kernel_server/tools.py | 2 +- packages/agent-os/modules/observability/README.md | 2 +- packages/agentmesh-integrations/openclaw-skill/SKILL.md | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/integrations/openshell.md b/docs/integrations/openshell.md index 18a17e0d..63c348e8 100644 --- a/docs/integrations/openshell.md +++ b/docs/integrations/openshell.md @@ -73,7 +73,7 @@ Install the toolkit as an [OpenClaw skill](../packages/agentmesh-integrations/op ```bash # Inside the sandbox -pip install agentmesh +pip install agentmesh-platform # Use the skill scripts scripts/check-policy.sh --action "web_search" --tokens 1500 --policy policy.yaml diff --git a/packages/agent-compliance/docs/submissions/owasp-genai-implementation-guide.md b/packages/agent-compliance/docs/submissions/owasp-genai-implementation-guide.md index b7ca868e..408933a6 100644 --- a/packages/agent-compliance/docs/submissions/owasp-genai-implementation-guide.md +++ b/packages/agent-compliance/docs/submissions/owasp-genai-implementation-guide.md @@ -12,7 +12,7 @@ The stack consists of four components: | Component | Role | Install | |---|---|---| | **Agent OS** | Governance kernel — policy, sandbox, memory, MCP security | `pip install agent-os-kernel` | -| **AgentMesh** | Identity & trust — DIDs, SPIFFE, handshake, reputation | `pip install agentmesh` | +| **AgentMesh** | Identity & trust — DIDs, SPIFFE, handshake, reputation | `pip install agentmesh-platform` | | **Agent SRE** | Observability — SLOs, anomaly detection, chaos, OpenTelemetry | `pip install agent-sre` | | **Agent Runtime** | Runtime control — kill switch, execution rings, saga rollback | `pip install agent-runtime` | diff --git a/packages/agent-mesh/src/agentmesh/cli/main.py b/packages/agent-mesh/src/agentmesh/cli/main.py index 9f15795e..5af4e295 100644 --- a/packages/agent-mesh/src/agentmesh/cli/main.py +++ b/packages/agent-mesh/src/agentmesh/cli/main.py @@ -261,7 +261,7 @@ def register(agent_dir: str, name: str = None): try: from agentmesh.identity import AgentIdentity except ImportError: - console.print("[red]Error: agentmesh is not installed. Run: pip install agentmesh[/red]") + console.print("[red]Error: agentmesh is not installed. Run: pip install agentmesh-platform[/red]") return identity = AgentIdentity.create(agent_name) diff --git a/packages/agent-mesh/src/agentmesh/transport/grpc_transport.py b/packages/agent-mesh/src/agentmesh/transport/grpc_transport.py index 417d1e25..a0b7034f 100644 --- a/packages/agent-mesh/src/agentmesh/transport/grpc_transport.py +++ b/packages/agent-mesh/src/agentmesh/transport/grpc_transport.py @@ -8,7 +8,7 @@ Requires the ``grpcio`` and ``grpcio-tools`` libraries:: - pip install agentmesh[grpc] + pip install agentmesh-platform[grpc] """ from __future__ import annotations @@ -41,7 +41,7 @@ def _require_grpc() -> None: if not HAS_GRPC: raise ImportError( "The 'grpcio' package is required for gRPC transport. " - "Install it with: pip install agentmesh[grpc]" + "Install it with: pip install agentmesh-platform[grpc]" ) diff --git a/packages/agent-os/modules/control-plane/src/agent_control_plane/lifecycle.py b/packages/agent-os/modules/control-plane/src/agent_control_plane/lifecycle.py index cf6bcee2..746e5fd5 100644 --- a/packages/agent-os/modules/control-plane/src/agent_control_plane/lifecycle.py +++ b/packages/agent-os/modules/control-plane/src/agent_control_plane/lifecycle.py @@ -2427,11 +2427,11 @@ def _compute_version(self, module_name: str) -> str: module = sys.modules.get(module_name) if module and hasattr(module, '__file__') and module.__file__: with open(module.__file__, 'rb') as f: - return hashlib.md5(f.read()).hexdigest() + return hashlib.sha256(f.read()).hexdigest() except Exception as e: logger.warning(f"Could not compute version for {module_name}: {e}") - return hashlib.md5(module_name.encode()).hexdigest() + return hashlib.sha256(module_name.encode()).hexdigest() async def check_for_changes(self, agent_id: str) -> bool: """Check if an agent's code has changed""" diff --git a/packages/agent-os/modules/control-plane/src/agent_control_plane/ml_safety.py b/packages/agent-os/modules/control-plane/src/agent_control_plane/ml_safety.py index 0c55b896..41f8f303 100644 --- a/packages/agent-os/modules/control-plane/src/agent_control_plane/ml_safety.py +++ b/packages/agent-os/modules/control-plane/src/agent_control_plane/ml_safety.py @@ -82,7 +82,7 @@ def from_text(text: str) -> 'EmbeddingVector': """Create a simplified embedding from text""" # In production, would call actual embedding model # This is a simplified hash-based approach for demonstration - vector_hash = hashlib.md5(text.lower().encode()).hexdigest() + vector_hash = hashlib.sha256(text.lower().encode()).hexdigest() return EmbeddingVector(text=text, vector_hash=vector_hash) diff --git a/packages/agent-os/modules/mcp-kernel-server/src/mcp_kernel_server/tools.py b/packages/agent-os/modules/mcp-kernel-server/src/mcp_kernel_server/tools.py index 8a8ae8c9..6b3cdf38 100644 --- a/packages/agent-os/modules/mcp-kernel-server/src/mcp_kernel_server/tools.py +++ b/packages/agent-os/modules/mcp-kernel-server/src/mcp_kernel_server/tools.py @@ -335,7 +335,7 @@ async def _verify_claim(self, claim: str, context: str, threshold: float) -> dic # responses = [await call_model(m, claim) for m in models] # For demo: Generate deterministic mock responses - claim_hash = int(hashlib.md5(claim.encode()).hexdigest()[:8], 16) + claim_hash = int(hashlib.sha256(claim.encode()).hexdigest()[:8], 16) # Simulate model responses (in production, actual API calls) responses = [] diff --git a/packages/agent-os/modules/observability/README.md b/packages/agent-os/modules/observability/README.md index 6e472fc6..60e75774 100644 --- a/packages/agent-os/modules/observability/README.md +++ b/packages/agent-os/modules/observability/README.md @@ -20,7 +20,7 @@ This package provides metrics, tracing, and dashboards for monitoring Agent OS d ### Install Package ```bash -pip install agent-os-observability +pip install agent-os-kernel[observability] ``` ### Basic Usage diff --git a/packages/agentmesh-integrations/openclaw-skill/SKILL.md b/packages/agentmesh-integrations/openclaw-skill/SKILL.md index f089e898..73f0e1d0 100644 --- a/packages/agentmesh-integrations/openclaw-skill/SKILL.md +++ b/packages/agentmesh-integrations/openclaw-skill/SKILL.md @@ -30,7 +30,7 @@ score trust, and maintain tamper-evident audit logs — all from your agent's co Install the AgentMesh governance CLI: ```bash -pip install agentmesh-governance +pip install agent-governance-toolkit ``` > If `agentmesh-governance` is not yet on PyPI, install directly from source: