Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
62642ad
fix: restore OpenShell ACS governance integration
imran-siddique Aug 13, 2026
5d8ac90
test: run OpenShell integration against native ACS
imran-siddique Aug 13, 2026
82dc0e8
test: align OpenShell stub escalation semantics
imran-siddique Aug 13, 2026
718ae4b
test: address OpenShell review findings
imran-siddique Aug 13, 2026
d059a59
Merge branch 'main' into agent/restore-openshell-acs-integration
imran-siddique Aug 19, 2026
11d9505
Merge remote-tracking branch 'origin/main' into agent/restore-openshe…
imran-siddique Sep 13, 2026
d57fc80
fix(openshell): declare the ACS version the runtime now supports
imran-siddique Sep 14, 2026
3037352
test(openshell): align approval checks with current ACS contract
imran-siddique Sep 14, 2026
964389c
merge: reconcile main for OpenShell CI
imran-siddique Sep 14, 2026
8518bc7
Merge branch 'main' into agent/restore-openshell-acs-integration
imran-siddique Sep 18, 2026
6f260a5
Merge branch 'main' into agent/restore-openshell-acs-integration
imran-siddique Sep 18, 2026
9d91986
Merge branch 'main' into agent/restore-openshell-acs-integration
imran-siddique Sep 18, 2026
110887b
Merge branch 'main' into agent/restore-openshell-acs-integration
Ricky-G Sep 20, 2026
efa8859
Merge branch 'main' into agent/restore-openshell-acs-integration
imran-siddique Sep 25, 2026
256132d
Merge branch 'main' into agent/restore-openshell-acs-integration
imran-siddique Sep 27, 2026
78933a9
Potential fix for pull request finding 'Unreachable code'
imran-siddique Sep 28, 2026
96ccf70
Merge branch 'main' into agent/restore-openshell-acs-integration
imran-siddique Sep 28, 2026
3a4f49f
Merge branch 'main' into agent/restore-openshell-acs-integration
imran-siddique Sep 28, 2026
7811682
Merge branch 'main' into agent/restore-openshell-acs-integration
imran-siddique Sep 28, 2026
1fd09e4
Merge branch 'main' into agent/restore-openshell-acs-integration
imran-siddique Sep 29, 2026
ce8ee4e
fix(openshell): execute the approved command and survive in-flight te…
imran-siddique Sep 29, 2026
ee7f569
fix(openshell): evaluate any argv iterable, and run the evaluated cwd
imran-siddique Sep 30, 2026
e2225fe
test(openshell): spell the user-list test id as cspell accepts
imran-siddique Sep 30, 2026
6a8fae4
Merge branch 'main' into agent/restore-openshell-acs-integration
imran-siddique Oct 1, 2026
542ac06
Merge branch 'main' into agent/restore-openshell-acs-integration
imran-siddique Oct 5, 2026
0f44912
Merge branch 'main' into agent/restore-openshell-acs-integration
imran-siddique Oct 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .cspell-repo-terms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ contentsafety
contentsource
contenttype
contextlib
contextmanager
contextvars
contoso
conv
Expand Down Expand Up @@ -579,7 +580,9 @@ fromlist
fromtimestamp
frontmatter
frozenset
fsdecode
fsencode
fspath
fullmatch
gazetted
gemini
Expand All @@ -590,6 +593,7 @@ geofencing
geomatch
getattr
getattribute
getcwd
getenv
gethostname
getitem
Expand Down Expand Up @@ -853,6 +857,7 @@ pathed
pathext
pathexts
pathlib
pathlike
pathsep
pathspec
pathspecs
Expand All @@ -873,6 +878,7 @@ policydefaults
policydocument
policyengine
popen
popenargs
popia
popitem
popleft
Expand Down
34 changes: 34 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,8 @@ jobs:
import-module: openai_agents_agentmesh
- package: openai-agents-trust
import-module: openai_agents_trust
- package: openshell-skill
import-module: openshell_agentmesh
- package: pydantic-ai-governance
import-module: pydantic_ai_governance
- package: cedarling-acs
Expand Down Expand Up @@ -921,6 +923,38 @@ jobs:
else
echo "::warning::ci-test.txt not found at $CI_TEST_REQS — skipping shared test deps"
fi
- name: Clean wheel install of the openshell extra
# The adapter imports agent_control_specification directly, so the
# [openshell] extra must bring ACS into an environment that has nothing
# else from this repository. ACS is supplied only through --find-links,
# so the install fails if the extra stops requiring it.
if: matrix.package == 'openshell-skill'
run: |
set -euo pipefail
WHEELS="$RUNNER_TEMP/openshell-wheels"
pip wheel --no-cache-dir --no-deps --no-build-isolation -w "$WHEELS" ./policy-engine/sdk/python
pip wheel --no-cache-dir --no-deps -w "$WHEELS" \
./agent-governance-python/agent-governance-toolkit-core \
./agent-governance-python/agent-governance-toolkit-integrations
python -m venv "$RUNNER_TEMP/openshell-clean"
CLEAN="$RUNNER_TEMP/openshell-clean/bin"
"$CLEAN/pip" install --no-cache-dir --find-links "$WHEELS" \
"$WHEELS"/agent_governance_toolkit_core-*.whl \
"$(ls "$WHEELS"/agent_governance_toolkit_integrations-*.whl)[openshell]"
"$CLEAN/python" - <<'PY'
from importlib.metadata import requires, version

declared = [
r for r in (requires("agent-governance-toolkit-integrations") or [])
if r.startswith("agent-control-specification")
and "extra ==" in r.replace('"', "'") and "'openshell'" in r.replace('"', "'")
]
assert declared, "the [openshell] extra does not declare agent-control-specification"
import agent_control_specification # noqa: F401
from openshell_agentmesh import GovernanceSkill, governed_shell # noqa: F401
print("clean install OK:", declared[0], "installed", version("agent-control-specification"))
PY
"$CLEAN/openshell-governance" --help > /dev/null
- name: Validate Python syntax
working-directory: agent-governance-python/agentmesh-integrations/${{ matrix.package }}
run: |
Expand Down
11 changes: 6 additions & 5 deletions BREAKING_CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -570,11 +570,12 @@ keeps its own `PolicyDecision` enum, `agent_os` re-exports a `PolicyRule` from
system that was never part of the v4 language.

Framework integrations lose their local policy surfaces: `GovernancePolicy`,
`GovernancePolicyChecker`, `GovernanceComponent`, `GovernanceSkill`,
`GovernanceToolset`, `PolicyGuardrailConfig`, `PatternType`,
`ShellPolicyViolation`, `load_policy_yaml`, `governed_shell`,
`policy_input_guardrail`, and `content_output_guardrail`. Each took a local
policy object; each now takes an `AgentControl`.
`GovernancePolicyChecker`, `GovernanceComponent`, `GovernanceToolset`,
`PolicyGuardrailConfig`, `PatternType`, `load_policy_yaml`,
`policy_input_guardrail`, and `content_output_guardrail`. The OpenShell adapter
retains `GovernanceSkill`, `ShellPolicyViolation`, and `governed_shell` as
host-interception helpers, but `GovernanceSkill` now takes an `AgentControl`
instead of interpreting a local policy object.

The `cedarling-agentmesh` backend and `CedarlingBackend` are removed with the
consolidated package extra that pulled them in. The backend implemented the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ Install the base package and add extras for the frameworks you use:
```bash
pip install agent-governance-toolkit-integrations[langchain]
pip install agent-governance-toolkit-integrations[crewai,openai-agents]
pip install agent-governance-toolkit-integrations[openshell]
```

The OpenShell extra provides fail-closed ACS governance for process creation
inside OpenShell-hosted Python agents.

See the
[migration guide](https://github.com/microsoft/agent-governance-toolkit/blob/main/docs/package-consolidation/MIGRATION.md)
for details on moving from the old per-framework packages.
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[build-system]
requires = ["hatchling>=1.18"]
build-backend = "hatchling.build"
Expand Down Expand Up @@ -52,7 +52,9 @@
avp = []
nostr-wot = []
structural-authz = []
openshell = ["pyyaml>=6.0,<7.0"]
# The adapter imports agent_control_specification directly; pin the same
# range agent-governance-toolkit-core declares.
openshell = ["agent-control-specification>=0.4.0b0,<0.5.0"]
audit-export = []

dev = [
Expand All @@ -67,6 +69,9 @@
Repository = "https://github.com/microsoft/agent-governance-toolkit"
"Bug Tracker" = "https://github.com/microsoft/agent-governance-toolkit/issues"

[project.scripts]
openshell-governance = "openshell_agentmesh.cli:main"

# ============================================================================
# Hatchling: pull adapter sources from agentmesh-integrations/
# ============================================================================
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
# openshell-agentmesh
# OpenShell AgentMesh integration

This compatibility package is deprecated. The OpenShell governance skill
(`GovernanceSkill`, `ShellPolicyViolation`, `governed_shell`) was removed in
the v5 ACS migration and has no OpenShell-specific replacement: importing
`openshell_agentmesh` now only emits a `DeprecationWarning`.

To govern an OpenShell-hosted agent, build an `AgentControl` from an ACS
manifest and evaluate intervention points in the host:
This adapter applies Agent Control Specification policy to process creation by
Python agents hosted in an OpenShell sandbox. It intercepts `subprocess.run`,
`subprocess.Popen`, `os.system`, and `os.popen` in an explicit context and
evaluates each command at the `pre_tool_call` intervention point as the
`shell.execute` tool.

```python
from agent_control_specification import AgentControl
import subprocess

from openshell_agentmesh import GovernanceSkill, governed_shell

control = AgentControl.from_path("policies/agt-manifest.yaml")
skill = GovernanceSkill.from_manifest("openshell-policy.yaml")
with governed_shell(skill):
subprocess.run(["git", "status"], check=True)
```

See
[BREAKING_CHANGES.md](../../../BREAKING_CHANGES.md)
for the removed-symbols record and migration guidance.
The ACS policy target contains `executable`, `argv`, `command`, `shell`, `api`,
`cwd`, OpenShell sandbox metadata, and caller-supplied context. Deny and
unresolved escalation verdicts stop execution. Transform verdicts may replace
the command. Policy evaluation errors fail closed.

Install the adapter through the consolidated integrations distribution.

```bash
pip install "agent-governance-toolkit-integrations[openshell]"
```
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
import warnings
warnings.warn(
"openshell-agentmesh is deprecated: the OpenShell governance skill "
"(GovernanceSkill, ShellPolicyViolation, governed_shell) was removed in "
"the v5 ACS migration and has no OpenShell-specific replacement. Build "
"an AgentControl from an ACS manifest (agent_control_specification) and "
"evaluate intervention points in the host. See "
"https://github.com/microsoft/agent-governance-toolkit/blob/main/BREAKING_CHANGES.md",
DeprecationWarning,
stacklevel=2,
)
"""Agent Control Specification integration for OpenShell-hosted agents."""

from .skill import GovernanceSkill, ShellPolicyViolation, governed_shell

__all__ = ["GovernanceSkill", "ShellPolicyViolation", "governed_shell"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
"""Command-line policy check for the OpenShell ACS integration."""

from __future__ import annotations

import argparse
import json
import sys

from .skill import GovernanceSkill, ShellPolicyViolation


def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(prog="openshell-governance")
parser.add_argument("--manifest", required=True, help="Path to an ACS manifest")
parser.add_argument("--agent-id")
parser.add_argument("--shell", action="store_true")
parser.add_argument("command", nargs=argparse.REMAINDER)
args = parser.parse_args(argv)
if not args.command:
parser.error("a command is required")

command: object = " ".join(args.command) if args.shell else args.command
skill = GovernanceSkill.from_manifest(args.manifest, agent_id=args.agent_id)
try:
transformed, result = skill.authorize_shell_command(
command, api="openshell-governance", shell=args.shell
)
except ShellPolicyViolation as exc:
print(
json.dumps(
{"decision": exc.result.verdict.decision.value, "reason": str(exc)}
)
)
return 1
except PermissionError as exc:
print(json.dumps({"decision": "deny", "reason": str(exc)}))
return 1
print(
json.dumps(
{
"decision": result.verdict.decision.value,
"command": transformed,
"reason": result.verdict.reason,
}
)
)
return 0


if __name__ == "__main__":
sys.exit(main())
Loading
Loading