agentmesh_runtime 3.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
"""
|
|
4
|
+
Agent Runtime — Execution supervisor for multi-agent sessions.
|
|
5
|
+
|
|
6
|
+
This package is the successor to ``agent-hypervisor``. It re-exports the
|
|
7
|
+
full public API from ``hypervisor`` so that callers can migrate their imports
|
|
8
|
+
incrementally::
|
|
9
|
+
|
|
10
|
+
# Old
|
|
11
|
+
from hypervisor import Hypervisor, SessionConfig
|
|
12
|
+
# New (equivalent)
|
|
13
|
+
from agent_runtime import Hypervisor, SessionConfig
|
|
14
|
+
|
|
15
|
+
The ``agent-hypervisor`` package remains available for backward compatibility
|
|
16
|
+
and will be deprecated in a future release.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from hypervisor import ( # noqa: F401
|
|
20
|
+
__version__,
|
|
21
|
+
# Core
|
|
22
|
+
Hypervisor,
|
|
23
|
+
# Models
|
|
24
|
+
ConsistencyMode,
|
|
25
|
+
ExecutionRing,
|
|
26
|
+
ReversibilityLevel,
|
|
27
|
+
SessionConfig,
|
|
28
|
+
SessionState,
|
|
29
|
+
# Session
|
|
30
|
+
SharedSessionObject,
|
|
31
|
+
SessionVFS,
|
|
32
|
+
VFSEdit,
|
|
33
|
+
VFSPermissionError,
|
|
34
|
+
VectorClock,
|
|
35
|
+
VectorClockManager,
|
|
36
|
+
CausalViolationError,
|
|
37
|
+
IntentLockManager,
|
|
38
|
+
LockIntent,
|
|
39
|
+
LockContentionError,
|
|
40
|
+
DeadlockError,
|
|
41
|
+
IsolationLevel,
|
|
42
|
+
# Liability
|
|
43
|
+
VouchRecord,
|
|
44
|
+
VouchingEngine,
|
|
45
|
+
SlashingEngine,
|
|
46
|
+
LiabilityMatrix,
|
|
47
|
+
CausalAttributor,
|
|
48
|
+
AttributionResult,
|
|
49
|
+
QuarantineManager,
|
|
50
|
+
QuarantineReason,
|
|
51
|
+
LiabilityLedger,
|
|
52
|
+
LedgerEntryType,
|
|
53
|
+
# Rings
|
|
54
|
+
RingEnforcer,
|
|
55
|
+
ActionClassifier,
|
|
56
|
+
RingElevationManager,
|
|
57
|
+
RingElevation,
|
|
58
|
+
ElevationDenialReason,
|
|
59
|
+
RingBreachDetector,
|
|
60
|
+
BreachSeverity,
|
|
61
|
+
# Reversibility
|
|
62
|
+
ReversibilityRegistry,
|
|
63
|
+
# Saga
|
|
64
|
+
SagaOrchestrator,
|
|
65
|
+
SagaTimeoutError,
|
|
66
|
+
SagaState,
|
|
67
|
+
StepState,
|
|
68
|
+
FanOutOrchestrator,
|
|
69
|
+
FanOutPolicy,
|
|
70
|
+
CheckpointManager,
|
|
71
|
+
SemanticCheckpoint,
|
|
72
|
+
SagaDSLParser,
|
|
73
|
+
SagaDefinition,
|
|
74
|
+
# Audit
|
|
75
|
+
DeltaEngine,
|
|
76
|
+
CommitmentEngine,
|
|
77
|
+
EphemeralGC,
|
|
78
|
+
# Verification
|
|
79
|
+
TransactionHistoryVerifier,
|
|
80
|
+
# Observability
|
|
81
|
+
HypervisorEventBus,
|
|
82
|
+
EventType,
|
|
83
|
+
HypervisorEvent,
|
|
84
|
+
CausalTraceId,
|
|
85
|
+
# Security
|
|
86
|
+
AgentRateLimiter,
|
|
87
|
+
RateLimitExceeded,
|
|
88
|
+
KillSwitch,
|
|
89
|
+
KillResult,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
__all__ = [
|
|
93
|
+
"__version__",
|
|
94
|
+
"Hypervisor",
|
|
95
|
+
"ConsistencyMode",
|
|
96
|
+
"ExecutionRing",
|
|
97
|
+
"ReversibilityLevel",
|
|
98
|
+
"SessionConfig",
|
|
99
|
+
"SessionState",
|
|
100
|
+
"SharedSessionObject",
|
|
101
|
+
"SessionVFS",
|
|
102
|
+
"VFSEdit",
|
|
103
|
+
"VFSPermissionError",
|
|
104
|
+
"VectorClock",
|
|
105
|
+
"VectorClockManager",
|
|
106
|
+
"CausalViolationError",
|
|
107
|
+
"IntentLockManager",
|
|
108
|
+
"LockIntent",
|
|
109
|
+
"LockContentionError",
|
|
110
|
+
"DeadlockError",
|
|
111
|
+
"IsolationLevel",
|
|
112
|
+
"VouchRecord",
|
|
113
|
+
"VouchingEngine",
|
|
114
|
+
"SlashingEngine",
|
|
115
|
+
"LiabilityMatrix",
|
|
116
|
+
"CausalAttributor",
|
|
117
|
+
"AttributionResult",
|
|
118
|
+
"QuarantineManager",
|
|
119
|
+
"QuarantineReason",
|
|
120
|
+
"LiabilityLedger",
|
|
121
|
+
"LedgerEntryType",
|
|
122
|
+
"RingEnforcer",
|
|
123
|
+
"ActionClassifier",
|
|
124
|
+
"RingElevationManager",
|
|
125
|
+
"RingElevation",
|
|
126
|
+
"ElevationDenialReason",
|
|
127
|
+
"RingBreachDetector",
|
|
128
|
+
"BreachSeverity",
|
|
129
|
+
"ReversibilityRegistry",
|
|
130
|
+
"SagaOrchestrator",
|
|
131
|
+
"SagaTimeoutError",
|
|
132
|
+
"SagaState",
|
|
133
|
+
"StepState",
|
|
134
|
+
"FanOutOrchestrator",
|
|
135
|
+
"FanOutPolicy",
|
|
136
|
+
"CheckpointManager",
|
|
137
|
+
"SemanticCheckpoint",
|
|
138
|
+
"SagaDSLParser",
|
|
139
|
+
"SagaDefinition",
|
|
140
|
+
"DeltaEngine",
|
|
141
|
+
"CommitmentEngine",
|
|
142
|
+
"EphemeralGC",
|
|
143
|
+
"TransactionHistoryVerifier",
|
|
144
|
+
"HypervisorEventBus",
|
|
145
|
+
"EventType",
|
|
146
|
+
"HypervisorEvent",
|
|
147
|
+
"CausalTraceId",
|
|
148
|
+
"AgentRateLimiter",
|
|
149
|
+
"RateLimitExceeded",
|
|
150
|
+
"KillSwitch",
|
|
151
|
+
"KillResult",
|
|
152
|
+
]
|
|
153
|
+
|
|
154
|
+
# ============================================================================
|
|
155
|
+
# Deployment Runtime (v3.0.2+)
|
|
156
|
+
# ============================================================================
|
|
157
|
+
|
|
158
|
+
from agent_runtime.deploy import (
|
|
159
|
+
DeploymentResult,
|
|
160
|
+
DeploymentStatus,
|
|
161
|
+
DeploymentTarget,
|
|
162
|
+
DockerDeployer,
|
|
163
|
+
GovernanceConfig,
|
|
164
|
+
KubernetesDeployer,
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# Update __all__ to include new exports
|
|
168
|
+
__all__ = [
|
|
169
|
+
*__all__,
|
|
170
|
+
"DeploymentResult",
|
|
171
|
+
"DeploymentStatus",
|
|
172
|
+
"DeploymentTarget",
|
|
173
|
+
"DockerDeployer",
|
|
174
|
+
"GovernanceConfig",
|
|
175
|
+
"KubernetesDeployer",
|
|
176
|
+
]
|
agent_runtime/deploy.py
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
"""Deployment runtime for governed AI agents.
|
|
4
|
+
|
|
5
|
+
Provides deployment targets for running governed agents in production:
|
|
6
|
+
- Docker containers with policy enforcement
|
|
7
|
+
- Kubernetes (AKS) pods with governance sidecars
|
|
8
|
+
- Local process with sandbox isolation
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import logging
|
|
14
|
+
import shutil
|
|
15
|
+
import subprocess
|
|
16
|
+
import tempfile
|
|
17
|
+
from dataclasses import dataclass, field
|
|
18
|
+
from enum import Enum
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Any, Protocol
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class DeploymentStatus(str, Enum):
|
|
26
|
+
PENDING = "pending"
|
|
27
|
+
DEPLOYING = "deploying"
|
|
28
|
+
RUNNING = "running"
|
|
29
|
+
STOPPED = "stopped"
|
|
30
|
+
FAILED = "failed"
|
|
31
|
+
TERMINATED = "terminated"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class GovernanceConfig:
|
|
36
|
+
"""Governance configuration injected into deployed agents."""
|
|
37
|
+
policy_path: str = ""
|
|
38
|
+
trust_level: str = "standard"
|
|
39
|
+
audit_enabled: bool = True
|
|
40
|
+
max_tool_calls: int = 100
|
|
41
|
+
rate_limit_rpm: int = 60
|
|
42
|
+
kill_switch_enabled: bool = True
|
|
43
|
+
retention_days: int = 180
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class DeploymentResult:
|
|
48
|
+
"""Result of a deployment operation."""
|
|
49
|
+
status: DeploymentStatus
|
|
50
|
+
target: str
|
|
51
|
+
agent_id: str
|
|
52
|
+
endpoint: str = ""
|
|
53
|
+
container_id: str = ""
|
|
54
|
+
error: str = ""
|
|
55
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class DeploymentTarget(Protocol):
|
|
59
|
+
"""Protocol for deployment targets."""
|
|
60
|
+
def deploy(self, agent_id: str, image: str, config: GovernanceConfig, **kwargs: Any) -> DeploymentResult: ...
|
|
61
|
+
def stop(self, agent_id: str) -> DeploymentResult: ...
|
|
62
|
+
def status(self, agent_id: str) -> DeploymentResult: ...
|
|
63
|
+
def logs(self, agent_id: str, tail: int = 100) -> str: ...
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class DockerDeployer:
|
|
67
|
+
"""Deploy governed agents as Docker containers.
|
|
68
|
+
|
|
69
|
+
Usage:
|
|
70
|
+
deployer = DockerDeployer()
|
|
71
|
+
result = deployer.deploy(
|
|
72
|
+
agent_id="analyst-001",
|
|
73
|
+
image="agent-os:latest",
|
|
74
|
+
config=GovernanceConfig(policy_path="/policies/strict.yaml"),
|
|
75
|
+
)
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
def __init__(self, network: str = "agent-governance", docker_cmd: str = "docker") -> None:
|
|
79
|
+
self._network = network
|
|
80
|
+
self._docker = docker_cmd
|
|
81
|
+
self._ensure_docker()
|
|
82
|
+
|
|
83
|
+
def _ensure_docker(self) -> None:
|
|
84
|
+
if not shutil.which(self._docker):
|
|
85
|
+
raise RuntimeError(f"{self._docker} not found in PATH")
|
|
86
|
+
|
|
87
|
+
def _run(self, args: list[str], check: bool = True) -> subprocess.CompletedProcess[str]:
|
|
88
|
+
cmd = [self._docker] + args
|
|
89
|
+
logger.debug("Running: %s", " ".join(cmd))
|
|
90
|
+
return subprocess.run(cmd, capture_output=True, text=True, check=check, timeout=60)
|
|
91
|
+
|
|
92
|
+
def deploy(self, agent_id: str, image: str, config: GovernanceConfig,
|
|
93
|
+
port: int = 0, env: dict[str, str] | None = None, **kwargs: Any) -> DeploymentResult:
|
|
94
|
+
container_name = f"agt-{agent_id}"
|
|
95
|
+
cmd = [
|
|
96
|
+
"run", "-d",
|
|
97
|
+
"--name", container_name,
|
|
98
|
+
"--network", self._network,
|
|
99
|
+
"--label", f"agt.agent-id={agent_id}",
|
|
100
|
+
"--label", "agt.managed=true",
|
|
101
|
+
"--restart", "unless-stopped",
|
|
102
|
+
# Security: drop all capabilities, add only what's needed
|
|
103
|
+
"--cap-drop", "ALL",
|
|
104
|
+
"--security-opt", "no-new-privileges",
|
|
105
|
+
"--read-only",
|
|
106
|
+
"--tmpfs", "/tmp:rw,noexec,nosuid",
|
|
107
|
+
# Governance config as env vars
|
|
108
|
+
"-e", f"AGT_POLICY_PATH={config.policy_path}",
|
|
109
|
+
"-e", f"AGT_TRUST_LEVEL={config.trust_level}",
|
|
110
|
+
"-e", f"AGT_AUDIT_ENABLED={str(config.audit_enabled).lower()}",
|
|
111
|
+
"-e", f"AGT_MAX_TOOL_CALLS={config.max_tool_calls}",
|
|
112
|
+
"-e", f"AGT_RATE_LIMIT_RPM={config.rate_limit_rpm}",
|
|
113
|
+
"-e", f"AGT_KILL_SWITCH={str(config.kill_switch_enabled).lower()}",
|
|
114
|
+
"-e", f"AGT_RETENTION_DAYS={config.retention_days}",
|
|
115
|
+
]
|
|
116
|
+
if port:
|
|
117
|
+
cmd.extend(["-p", f"127.0.0.1:{port}:8080"])
|
|
118
|
+
if env:
|
|
119
|
+
for k, v in env.items():
|
|
120
|
+
cmd.extend(["-e", f"{k}={v}"])
|
|
121
|
+
cmd.append(image)
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
# Ensure network exists
|
|
125
|
+
self._run(["network", "create", self._network], check=False)
|
|
126
|
+
result = self._run(cmd)
|
|
127
|
+
container_id = result.stdout.strip()[:12]
|
|
128
|
+
return DeploymentResult(
|
|
129
|
+
status=DeploymentStatus.RUNNING,
|
|
130
|
+
target="docker",
|
|
131
|
+
agent_id=agent_id,
|
|
132
|
+
container_id=container_id,
|
|
133
|
+
endpoint=f"http://localhost:{port}" if port else "",
|
|
134
|
+
)
|
|
135
|
+
except subprocess.CalledProcessError as e:
|
|
136
|
+
return DeploymentResult(
|
|
137
|
+
status=DeploymentStatus.FAILED,
|
|
138
|
+
target="docker",
|
|
139
|
+
agent_id=agent_id,
|
|
140
|
+
error=e.stderr.strip(),
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
def stop(self, agent_id: str) -> DeploymentResult:
|
|
144
|
+
container_name = f"agt-{agent_id}"
|
|
145
|
+
try:
|
|
146
|
+
self._run(["stop", container_name])
|
|
147
|
+
self._run(["rm", container_name])
|
|
148
|
+
return DeploymentResult(
|
|
149
|
+
status=DeploymentStatus.STOPPED,
|
|
150
|
+
target="docker",
|
|
151
|
+
agent_id=agent_id,
|
|
152
|
+
)
|
|
153
|
+
except subprocess.CalledProcessError as e:
|
|
154
|
+
return DeploymentResult(
|
|
155
|
+
status=DeploymentStatus.FAILED,
|
|
156
|
+
target="docker",
|
|
157
|
+
agent_id=agent_id,
|
|
158
|
+
error=e.stderr.strip(),
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
def status(self, agent_id: str) -> DeploymentResult:
|
|
162
|
+
container_name = f"agt-{agent_id}"
|
|
163
|
+
try:
|
|
164
|
+
result = self._run(["inspect", container_name, "--format", "{{.State.Status}}"])
|
|
165
|
+
state = result.stdout.strip()
|
|
166
|
+
status_map = {"running": DeploymentStatus.RUNNING, "exited": DeploymentStatus.STOPPED}
|
|
167
|
+
return DeploymentResult(
|
|
168
|
+
status=status_map.get(state, DeploymentStatus.FAILED),
|
|
169
|
+
target="docker",
|
|
170
|
+
agent_id=agent_id,
|
|
171
|
+
container_id=container_name,
|
|
172
|
+
)
|
|
173
|
+
except subprocess.CalledProcessError:
|
|
174
|
+
return DeploymentResult(
|
|
175
|
+
status=DeploymentStatus.STOPPED,
|
|
176
|
+
target="docker",
|
|
177
|
+
agent_id=agent_id,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
def logs(self, agent_id: str, tail: int = 100) -> str:
|
|
181
|
+
try:
|
|
182
|
+
result = self._run(["logs", f"agt-{agent_id}", "--tail", str(tail)])
|
|
183
|
+
return result.stdout
|
|
184
|
+
except subprocess.CalledProcessError:
|
|
185
|
+
return ""
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class KubernetesDeployer:
|
|
189
|
+
"""Deploy governed agents to Kubernetes (AKS) with governance sidecars.
|
|
190
|
+
|
|
191
|
+
Usage:
|
|
192
|
+
deployer = KubernetesDeployer(namespace="agents")
|
|
193
|
+
result = deployer.deploy(
|
|
194
|
+
agent_id="analyst-001",
|
|
195
|
+
image="myregistry.azurecr.io/agent-os:3.0.2",
|
|
196
|
+
config=GovernanceConfig(policy_path="/policies/strict.yaml"),
|
|
197
|
+
)
|
|
198
|
+
"""
|
|
199
|
+
|
|
200
|
+
def __init__(self, namespace: str = "agent-governance", kubectl_cmd: str = "kubectl",
|
|
201
|
+
context: str | None = None) -> None:
|
|
202
|
+
self._namespace = namespace
|
|
203
|
+
self._kubectl = kubectl_cmd
|
|
204
|
+
self._context = context
|
|
205
|
+
self._ensure_kubectl()
|
|
206
|
+
|
|
207
|
+
def _ensure_kubectl(self) -> None:
|
|
208
|
+
if not shutil.which(self._kubectl):
|
|
209
|
+
raise RuntimeError(f"{self._kubectl} not found in PATH")
|
|
210
|
+
|
|
211
|
+
def _run(self, args: list[str], check: bool = True) -> subprocess.CompletedProcess[str]:
|
|
212
|
+
cmd = [self._kubectl]
|
|
213
|
+
if self._context:
|
|
214
|
+
cmd.extend(["--context", self._context])
|
|
215
|
+
cmd.extend(args)
|
|
216
|
+
logger.debug("Running: %s", " ".join(cmd))
|
|
217
|
+
return subprocess.run(cmd, capture_output=True, text=True, check=check, timeout=120)
|
|
218
|
+
|
|
219
|
+
def _build_pod_manifest(self, agent_id: str, image: str, config: GovernanceConfig) -> dict[str, Any]:
|
|
220
|
+
return {
|
|
221
|
+
"apiVersion": "v1",
|
|
222
|
+
"kind": "Pod",
|
|
223
|
+
"metadata": {
|
|
224
|
+
"name": f"agt-{agent_id}",
|
|
225
|
+
"namespace": self._namespace,
|
|
226
|
+
"labels": {
|
|
227
|
+
"app.kubernetes.io/name": "agent-governance",
|
|
228
|
+
"app.kubernetes.io/component": "agent",
|
|
229
|
+
"agt.agent-id": agent_id,
|
|
230
|
+
"agt.trust-level": config.trust_level,
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
"spec": {
|
|
234
|
+
"securityContext": {
|
|
235
|
+
"runAsNonRoot": True,
|
|
236
|
+
"runAsUser": 1000,
|
|
237
|
+
"fsGroup": 1000,
|
|
238
|
+
"seccompProfile": {"type": "RuntimeDefault"},
|
|
239
|
+
},
|
|
240
|
+
"containers": [
|
|
241
|
+
{
|
|
242
|
+
"name": "agent",
|
|
243
|
+
"image": image,
|
|
244
|
+
"imagePullPolicy": "IfNotPresent",
|
|
245
|
+
"securityContext": {
|
|
246
|
+
"allowPrivilegeEscalation": False,
|
|
247
|
+
"capabilities": {"drop": ["ALL"]},
|
|
248
|
+
"readOnlyRootFilesystem": True,
|
|
249
|
+
},
|
|
250
|
+
"env": [
|
|
251
|
+
{"name": "AGT_POLICY_PATH", "value": config.policy_path},
|
|
252
|
+
{"name": "AGT_TRUST_LEVEL", "value": config.trust_level},
|
|
253
|
+
{"name": "AGT_AUDIT_ENABLED", "value": str(config.audit_enabled).lower()},
|
|
254
|
+
{"name": "AGT_MAX_TOOL_CALLS", "value": str(config.max_tool_calls)},
|
|
255
|
+
{"name": "AGT_RATE_LIMIT_RPM", "value": str(config.rate_limit_rpm)},
|
|
256
|
+
{"name": "AGT_KILL_SWITCH", "value": str(config.kill_switch_enabled).lower()},
|
|
257
|
+
{"name": "AGT_RETENTION_DAYS", "value": str(config.retention_days)},
|
|
258
|
+
],
|
|
259
|
+
"resources": {
|
|
260
|
+
"requests": {"cpu": "100m", "memory": "256Mi"},
|
|
261
|
+
"limits": {"cpu": "500m", "memory": "512Mi"},
|
|
262
|
+
},
|
|
263
|
+
"volumeMounts": [{"name": "tmp", "mountPath": "/tmp"}],
|
|
264
|
+
},
|
|
265
|
+
],
|
|
266
|
+
"volumes": [{"name": "tmp", "emptyDir": {"sizeLimit": "100Mi"}}],
|
|
267
|
+
"restartPolicy": "Always",
|
|
268
|
+
"terminationGracePeriodSeconds": 30,
|
|
269
|
+
},
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
def deploy(self, agent_id: str, image: str, config: GovernanceConfig, **kwargs: Any) -> DeploymentResult:
|
|
273
|
+
manifest = self._build_pod_manifest(agent_id, image, config)
|
|
274
|
+
manifest_json = json.dumps(manifest)
|
|
275
|
+
try:
|
|
276
|
+
# Ensure namespace
|
|
277
|
+
self._run(["create", "namespace", self._namespace], check=False)
|
|
278
|
+
tmp_dir = Path(tempfile.gettempdir())
|
|
279
|
+
manifest_path = tmp_dir / f"agt-{agent_id}-manifest.json"
|
|
280
|
+
try:
|
|
281
|
+
manifest_path.write_text(manifest_json, encoding="utf-8")
|
|
282
|
+
self._run(["apply", "-f", str(manifest_path)])
|
|
283
|
+
finally:
|
|
284
|
+
manifest_path.unlink(missing_ok=True)
|
|
285
|
+
return DeploymentResult(
|
|
286
|
+
status=DeploymentStatus.DEPLOYING,
|
|
287
|
+
target="kubernetes",
|
|
288
|
+
agent_id=agent_id,
|
|
289
|
+
metadata={"namespace": self._namespace},
|
|
290
|
+
)
|
|
291
|
+
except subprocess.CalledProcessError as e:
|
|
292
|
+
return DeploymentResult(
|
|
293
|
+
status=DeploymentStatus.FAILED,
|
|
294
|
+
target="kubernetes",
|
|
295
|
+
agent_id=agent_id,
|
|
296
|
+
error=e.stderr.strip(),
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
def stop(self, agent_id: str) -> DeploymentResult:
|
|
300
|
+
try:
|
|
301
|
+
self._run(["delete", "pod", f"agt-{agent_id}", "-n", self._namespace])
|
|
302
|
+
return DeploymentResult(
|
|
303
|
+
status=DeploymentStatus.TERMINATED,
|
|
304
|
+
target="kubernetes",
|
|
305
|
+
agent_id=agent_id,
|
|
306
|
+
)
|
|
307
|
+
except subprocess.CalledProcessError as e:
|
|
308
|
+
return DeploymentResult(
|
|
309
|
+
status=DeploymentStatus.FAILED,
|
|
310
|
+
target="kubernetes",
|
|
311
|
+
agent_id=agent_id,
|
|
312
|
+
error=e.stderr.strip(),
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
def status(self, agent_id: str) -> DeploymentResult:
|
|
316
|
+
try:
|
|
317
|
+
result = self._run([
|
|
318
|
+
"get", "pod", f"agt-{agent_id}",
|
|
319
|
+
"-n", self._namespace,
|
|
320
|
+
"-o", "jsonpath={.status.phase}",
|
|
321
|
+
])
|
|
322
|
+
phase = result.stdout.strip()
|
|
323
|
+
phase_map = {
|
|
324
|
+
"Running": DeploymentStatus.RUNNING,
|
|
325
|
+
"Pending": DeploymentStatus.DEPLOYING,
|
|
326
|
+
"Succeeded": DeploymentStatus.STOPPED,
|
|
327
|
+
"Failed": DeploymentStatus.FAILED,
|
|
328
|
+
}
|
|
329
|
+
return DeploymentResult(
|
|
330
|
+
status=phase_map.get(phase, DeploymentStatus.FAILED),
|
|
331
|
+
target="kubernetes",
|
|
332
|
+
agent_id=agent_id,
|
|
333
|
+
)
|
|
334
|
+
except subprocess.CalledProcessError:
|
|
335
|
+
return DeploymentResult(
|
|
336
|
+
status=DeploymentStatus.STOPPED,
|
|
337
|
+
target="kubernetes",
|
|
338
|
+
agent_id=agent_id,
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
def logs(self, agent_id: str, tail: int = 100) -> str:
|
|
342
|
+
try:
|
|
343
|
+
result = self._run([
|
|
344
|
+
"logs", f"agt-{agent_id}",
|
|
345
|
+
"-n", self._namespace,
|
|
346
|
+
"--tail", str(tail),
|
|
347
|
+
])
|
|
348
|
+
return result.stdout
|
|
349
|
+
except subprocess.CalledProcessError:
|
|
350
|
+
return ""
|
agent_runtime/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentmesh_runtime
|
|
3
|
+
Version: 3.1.0
|
|
4
|
+
Summary: Public Preview — AgentMesh Runtime: Execution supervisor for multi-agent sessions with privilege rings, saga orchestration, and audit trails
|
|
5
|
+
Project-URL: Homepage, https://github.com/microsoft/agent-governance-toolkit
|
|
6
|
+
Project-URL: Repository, https://github.com/microsoft/agent-governance-toolkit
|
|
7
|
+
Project-URL: Documentation, https://github.com/microsoft/agent-governance-toolkit/tree/main/packages/agent-runtime
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/microsoft/agent-governance-toolkit/issues
|
|
9
|
+
Author-email: Microsoft Corporation <agentgovtoolkit@microsoft.com>
|
|
10
|
+
Maintainer-email: Agent Governance Toolkit Team <agentgovtoolkit@microsoft.com>
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: agents,ai,audit,execution-rings,governance,hash-chain,liability,multi-agent,runtime,safety,saga,shared-sessions,trust
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.11
|
|
26
|
+
Requires-Dist: agent-hypervisor<4.0,>=2.1.0
|
|
27
|
+
Requires-Dist: jsonschema<5.0,>=4.0.0
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
<div align="center">
|
|
31
|
+
|
|
32
|
+
# AgentMesh Runtime
|
|
33
|
+
|
|
34
|
+
**Execution supervisor for multi-agent sessions — privilege rings, saga orchestration, and governance enforcement**
|
|
35
|
+
|
|
36
|
+
*Part of the [Agent Governance Toolkit](https://github.com/microsoft/agent-governance-toolkit)*
|
|
37
|
+
|
|
38
|
+
[](https://github.com/microsoft/agent-governance-toolkit/actions/workflows/ci.yml)
|
|
39
|
+
[](../../LICENSE)
|
|
40
|
+
[](https://python.org)
|
|
41
|
+
[](https://pypi.org/project/agentmesh-runtime/)
|
|
42
|
+
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
> [!IMPORTANT]
|
|
46
|
+
> **Public Preview** — The `agentmesh-runtime` package on PyPI is a Microsoft-signed
|
|
47
|
+
> public preview release. APIs may change before GA.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
> **Note:** This package was renamed from `agent-runtime` to `agentmesh-runtime` to avoid a PyPI
|
|
52
|
+
> name collision with the AutoGen team's package. The `agent-hypervisor` package remains the
|
|
53
|
+
> canonical upstream implementation; `agentmesh-runtime` is a thin re-export wrapper for
|
|
54
|
+
> incremental import migration.
|
|
55
|
+
|
|
56
|
+
## What is Agent Runtime?
|
|
57
|
+
|
|
58
|
+
Agent Runtime provides **execution-level supervision** for autonomous AI agents. While Agent OS handles
|
|
59
|
+
policy decisions and AgentMesh handles trust/identity, Agent Runtime enforces those decisions at the
|
|
60
|
+
session level:
|
|
61
|
+
|
|
62
|
+
- **Execution Rings** — 4-tier privilege model (Ring 0–3) controlling what agents can do at runtime
|
|
63
|
+
- **Shared Sessions** — Multi-agent session management with consistency modes (strict, eventual, causal)
|
|
64
|
+
- **Saga Orchestration** — Compensating transactions for multi-step agent workflows
|
|
65
|
+
- **Kill Switch** — Immediate termination with audit trail and blast radius containment
|
|
66
|
+
- **Joint Liability** — Attribution tracking across multi-agent collaborations
|
|
67
|
+
- **Audit Trails** — Hash-chained, append-only execution logs
|
|
68
|
+
|
|
69
|
+
## Quick Start
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install agentmesh-runtime
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from hypervisor import Hypervisor, SessionConfig, ConsistencyMode
|
|
77
|
+
|
|
78
|
+
# Create the runtime supervisor
|
|
79
|
+
hv = Hypervisor()
|
|
80
|
+
|
|
81
|
+
# Create a governed session
|
|
82
|
+
session = await hv.create_session(
|
|
83
|
+
config=SessionConfig(consistency_mode=ConsistencyMode.EVENTUAL)
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Execute with privilege enforcement
|
|
87
|
+
result = await session.execute(
|
|
88
|
+
agent_id="researcher-1",
|
|
89
|
+
action="tool_call",
|
|
90
|
+
tool="web_search",
|
|
91
|
+
ring=2 # restricted privilege ring
|
|
92
|
+
)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Architecture
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
99
|
+
│ Agent Runtime │
|
|
100
|
+
├─────────────┬──────────────────┬──────────────────┬─────────────────┤
|
|
101
|
+
│ Execution │ Session │ Saga │ Liability │
|
|
102
|
+
│ Rings │ Management │ Orchestration │ Tracking │
|
|
103
|
+
│ │ │ │ │
|
|
104
|
+
│ Ring 0: │ Create/join │ Multi-step │ Attribution │
|
|
105
|
+
│ System │ Consistency │ Compensation │ Vouching │
|
|
106
|
+
│ Ring 1: │ Checkpoints │ Rollback │ Slashing │
|
|
107
|
+
│ Trusted │ Merge/fork │ Recovery │ Quarantine │
|
|
108
|
+
│ Ring 2: │ │ │ │
|
|
109
|
+
│ Standard │ │ │ │
|
|
110
|
+
│ Ring 3: │ │ │ │
|
|
111
|
+
│ Sandboxed │ │ │ │
|
|
112
|
+
└─────────────┴──────────────────┴──────────────────┴─────────────────┘
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Ecosystem
|
|
116
|
+
|
|
117
|
+
Agent Runtime is one of 7 packages in the Agent Governance Toolkit:
|
|
118
|
+
|
|
119
|
+
| Package | Role |
|
|
120
|
+
|---------|------|
|
|
121
|
+
| **Agent OS** | Policy engine — deterministic action evaluation |
|
|
122
|
+
| **AgentMesh** | Trust infrastructure — identity, credentials, protocol bridges |
|
|
123
|
+
| **AgentMesh Runtime** | Execution supervisor — rings, sessions, sagas *(this package)* |
|
|
124
|
+
| **Agent SRE** | Reliability — SLOs, circuit breakers, chaos testing |
|
|
125
|
+
| **Agent Compliance** | Regulatory compliance — GDPR, HIPAA, SOX frameworks |
|
|
126
|
+
| **Agent Marketplace** | Plugin lifecycle — discover, install, verify, sign |
|
|
127
|
+
| **Agent Lightning** | RL training governance — governed runners, policy rewards |
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT — see [LICENSE](../../LICENSE).
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
agent_runtime/__init__.py,sha256=41lO5_bT5jh4elELK1i0cDBSf-8aUu7el9w7PtbBU-A,3934
|
|
2
|
+
agent_runtime/deploy.py,sha256=baKabHZ6cmsM9_hLLQbtazpA5siAH4c7uHHy6CI4_EY,13415
|
|
3
|
+
agent_runtime/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
agentmesh_runtime-3.1.0.dist-info/METADATA,sha256=aV8FApevgkMDk7UBMWNzJw4yJ3Nis5mg1D5q9WBmFAk,6458
|
|
5
|
+
agentmesh_runtime-3.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
6
|
+
agentmesh_runtime-3.1.0.dist-info/licenses/LICENSE,sha256=ffINzfkZfplFwUhY1Bxg8RtSuT5baeK2NBa4dNWY0yI,1074
|
|
7
|
+
agentmesh_runtime-3.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Microsoft Corporation.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|