agentmesh-platform 1.0.0a1__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.
- agentmesh/__init__.py +119 -0
- agentmesh/cli/__init__.py +10 -0
- agentmesh/cli/main.py +405 -0
- agentmesh/governance/__init__.py +26 -0
- agentmesh/governance/audit.py +381 -0
- agentmesh/governance/compliance.py +447 -0
- agentmesh/governance/policy.py +385 -0
- agentmesh/governance/shadow.py +266 -0
- agentmesh/identity/__init__.py +30 -0
- agentmesh/identity/agent_id.py +319 -0
- agentmesh/identity/credentials.py +323 -0
- agentmesh/identity/delegation.py +281 -0
- agentmesh/identity/risk.py +279 -0
- agentmesh/identity/spiffe.py +230 -0
- agentmesh/identity/sponsor.py +178 -0
- agentmesh/reward/__init__.py +19 -0
- agentmesh/reward/engine.py +454 -0
- agentmesh/reward/learning.py +287 -0
- agentmesh/reward/scoring.py +203 -0
- agentmesh/trust/__init__.py +19 -0
- agentmesh/trust/bridge.py +386 -0
- agentmesh/trust/capability.py +293 -0
- agentmesh/trust/handshake.py +334 -0
- agentmesh_platform-1.0.0a1.dist-info/METADATA +332 -0
- agentmesh_platform-1.0.0a1.dist-info/RECORD +28 -0
- agentmesh_platform-1.0.0a1.dist-info/WHEEL +4 -0
- agentmesh_platform-1.0.0a1.dist-info/entry_points.txt +2 -0
- agentmesh_platform-1.0.0a1.dist-info/licenses/LICENSE +190 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Adaptive Learning
|
|
3
|
+
|
|
4
|
+
The platform's ability to learn and adapt from agent behavior.
|
|
5
|
+
Supports tunable weights with A/B testing.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from datetime import datetime, timedelta
|
|
9
|
+
from typing import Optional, Callable
|
|
10
|
+
from pydantic import BaseModel, Field
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
import random
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class WeightExperiment:
|
|
17
|
+
"""An A/B test experiment for reward weights."""
|
|
18
|
+
|
|
19
|
+
experiment_id: str
|
|
20
|
+
name: str
|
|
21
|
+
|
|
22
|
+
# Control weights (current production)
|
|
23
|
+
control_weights: dict[str, float]
|
|
24
|
+
|
|
25
|
+
# Treatment weights (being tested)
|
|
26
|
+
treatment_weights: dict[str, float]
|
|
27
|
+
|
|
28
|
+
# Split
|
|
29
|
+
treatment_percentage: float = 0.1 # 10% in treatment
|
|
30
|
+
|
|
31
|
+
# Assignment
|
|
32
|
+
control_agents: set = None
|
|
33
|
+
treatment_agents: set = None
|
|
34
|
+
|
|
35
|
+
# Results
|
|
36
|
+
control_scores: list = None
|
|
37
|
+
treatment_scores: list = None
|
|
38
|
+
|
|
39
|
+
# Status
|
|
40
|
+
started_at: datetime = None
|
|
41
|
+
ended_at: datetime = None
|
|
42
|
+
|
|
43
|
+
def __post_init__(self):
|
|
44
|
+
self.control_agents = set()
|
|
45
|
+
self.treatment_agents = set()
|
|
46
|
+
self.control_scores = []
|
|
47
|
+
self.treatment_scores = []
|
|
48
|
+
self.started_at = datetime.utcnow()
|
|
49
|
+
|
|
50
|
+
def assign_agent(self, agent_did: str) -> str:
|
|
51
|
+
"""Assign an agent to control or treatment."""
|
|
52
|
+
if agent_did in self.control_agents:
|
|
53
|
+
return "control"
|
|
54
|
+
if agent_did in self.treatment_agents:
|
|
55
|
+
return "treatment"
|
|
56
|
+
|
|
57
|
+
# Random assignment
|
|
58
|
+
if random.random() < self.treatment_percentage:
|
|
59
|
+
self.treatment_agents.add(agent_did)
|
|
60
|
+
return "treatment"
|
|
61
|
+
else:
|
|
62
|
+
self.control_agents.add(agent_did)
|
|
63
|
+
return "control"
|
|
64
|
+
|
|
65
|
+
def record_score(self, agent_did: str, score: int) -> None:
|
|
66
|
+
"""Record a score observation."""
|
|
67
|
+
if agent_did in self.treatment_agents:
|
|
68
|
+
self.treatment_scores.append(score)
|
|
69
|
+
else:
|
|
70
|
+
self.control_scores.append(score)
|
|
71
|
+
|
|
72
|
+
def get_results(self) -> dict:
|
|
73
|
+
"""Get experiment results."""
|
|
74
|
+
control_avg = (
|
|
75
|
+
sum(self.control_scores) / len(self.control_scores)
|
|
76
|
+
if self.control_scores else 0
|
|
77
|
+
)
|
|
78
|
+
treatment_avg = (
|
|
79
|
+
sum(self.treatment_scores) / len(self.treatment_scores)
|
|
80
|
+
if self.treatment_scores else 0
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
"experiment_id": self.experiment_id,
|
|
85
|
+
"name": self.name,
|
|
86
|
+
"control_count": len(self.control_agents),
|
|
87
|
+
"treatment_count": len(self.treatment_agents),
|
|
88
|
+
"control_avg_score": control_avg,
|
|
89
|
+
"treatment_avg_score": treatment_avg,
|
|
90
|
+
"lift": treatment_avg - control_avg,
|
|
91
|
+
"lift_pct": ((treatment_avg - control_avg) / control_avg * 100) if control_avg else 0,
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class WeightOptimizer:
|
|
96
|
+
"""
|
|
97
|
+
Optimizer for reward dimension weights.
|
|
98
|
+
|
|
99
|
+
Supports:
|
|
100
|
+
- A/B testing of weight configurations
|
|
101
|
+
- Automatic weight tuning
|
|
102
|
+
- Statistical significance testing
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
def __init__(self):
|
|
106
|
+
self._experiments: dict[str, WeightExperiment] = {}
|
|
107
|
+
self._active_experiment: Optional[str] = None
|
|
108
|
+
|
|
109
|
+
def start_experiment(
|
|
110
|
+
self,
|
|
111
|
+
name: str,
|
|
112
|
+
control_weights: dict[str, float],
|
|
113
|
+
treatment_weights: dict[str, float],
|
|
114
|
+
treatment_pct: float = 0.1,
|
|
115
|
+
) -> WeightExperiment:
|
|
116
|
+
"""Start a weight A/B test."""
|
|
117
|
+
import uuid
|
|
118
|
+
exp_id = f"exp_{uuid.uuid4().hex[:12]}"
|
|
119
|
+
|
|
120
|
+
experiment = WeightExperiment(
|
|
121
|
+
experiment_id=exp_id,
|
|
122
|
+
name=name,
|
|
123
|
+
control_weights=control_weights,
|
|
124
|
+
treatment_weights=treatment_weights,
|
|
125
|
+
treatment_percentage=treatment_pct,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
self._experiments[exp_id] = experiment
|
|
129
|
+
self._active_experiment = exp_id
|
|
130
|
+
|
|
131
|
+
return experiment
|
|
132
|
+
|
|
133
|
+
def get_weights_for_agent(self, agent_did: str) -> dict[str, float]:
|
|
134
|
+
"""Get the appropriate weights for an agent (considering experiments)."""
|
|
135
|
+
if not self._active_experiment:
|
|
136
|
+
return {} # Use default
|
|
137
|
+
|
|
138
|
+
experiment = self._experiments[self._active_experiment]
|
|
139
|
+
group = experiment.assign_agent(agent_did)
|
|
140
|
+
|
|
141
|
+
if group == "treatment":
|
|
142
|
+
return experiment.treatment_weights
|
|
143
|
+
else:
|
|
144
|
+
return experiment.control_weights
|
|
145
|
+
|
|
146
|
+
def record_observation(self, agent_did: str, score: int) -> None:
|
|
147
|
+
"""Record a score observation for active experiment."""
|
|
148
|
+
if self._active_experiment:
|
|
149
|
+
self._experiments[self._active_experiment].record_score(agent_did, score)
|
|
150
|
+
|
|
151
|
+
def end_experiment(self, experiment_id: Optional[str] = None) -> dict:
|
|
152
|
+
"""End an experiment and get results."""
|
|
153
|
+
exp_id = experiment_id or self._active_experiment
|
|
154
|
+
if not exp_id or exp_id not in self._experiments:
|
|
155
|
+
return {"error": "No experiment found"}
|
|
156
|
+
|
|
157
|
+
experiment = self._experiments[exp_id]
|
|
158
|
+
experiment.ended_at = datetime.utcnow()
|
|
159
|
+
|
|
160
|
+
if exp_id == self._active_experiment:
|
|
161
|
+
self._active_experiment = None
|
|
162
|
+
|
|
163
|
+
return experiment.get_results()
|
|
164
|
+
|
|
165
|
+
def should_adopt_treatment(self, experiment_id: str, min_lift_pct: float = 5.0) -> bool:
|
|
166
|
+
"""Check if treatment should be adopted."""
|
|
167
|
+
if experiment_id not in self._experiments:
|
|
168
|
+
return False
|
|
169
|
+
|
|
170
|
+
results = self._experiments[experiment_id].get_results()
|
|
171
|
+
|
|
172
|
+
# Check statistical significance (simplified)
|
|
173
|
+
if results["control_count"] < 100 or results["treatment_count"] < 10:
|
|
174
|
+
return False # Not enough data
|
|
175
|
+
|
|
176
|
+
return results["lift_pct"] >= min_lift_pct
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class AdaptiveLearner:
|
|
180
|
+
"""
|
|
181
|
+
Learns optimal policies from agent behavior.
|
|
182
|
+
|
|
183
|
+
Features:
|
|
184
|
+
- Behavioral pattern detection
|
|
185
|
+
- Anomaly identification
|
|
186
|
+
- Policy recommendation
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
def __init__(self):
|
|
190
|
+
self._patterns: dict[str, list] = {} # agent_did -> [patterns]
|
|
191
|
+
self._anomalies: list = []
|
|
192
|
+
|
|
193
|
+
def observe(
|
|
194
|
+
self,
|
|
195
|
+
agent_did: str,
|
|
196
|
+
action: str,
|
|
197
|
+
context: dict,
|
|
198
|
+
outcome: str,
|
|
199
|
+
score_impact: int,
|
|
200
|
+
) -> None:
|
|
201
|
+
"""Observe an agent action for learning."""
|
|
202
|
+
if agent_did not in self._patterns:
|
|
203
|
+
self._patterns[agent_did] = []
|
|
204
|
+
|
|
205
|
+
observation = {
|
|
206
|
+
"action": action,
|
|
207
|
+
"context_keys": list(context.keys()),
|
|
208
|
+
"outcome": outcome,
|
|
209
|
+
"score_impact": score_impact,
|
|
210
|
+
"timestamp": datetime.utcnow().isoformat(),
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
self._patterns[agent_did].append(observation)
|
|
214
|
+
|
|
215
|
+
# Detect anomalies
|
|
216
|
+
if score_impact < -50: # Large negative impact
|
|
217
|
+
self._anomalies.append({
|
|
218
|
+
"agent_did": agent_did,
|
|
219
|
+
"observation": observation,
|
|
220
|
+
"type": "large_negative_impact",
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
def get_agent_patterns(self, agent_did: str) -> list:
|
|
224
|
+
"""Get learned patterns for an agent."""
|
|
225
|
+
return self._patterns.get(agent_did, [])
|
|
226
|
+
|
|
227
|
+
def get_recommendations(self, agent_did: str) -> list[str]:
|
|
228
|
+
"""Get policy recommendations based on patterns."""
|
|
229
|
+
patterns = self._patterns.get(agent_did, [])
|
|
230
|
+
|
|
231
|
+
if not patterns:
|
|
232
|
+
return []
|
|
233
|
+
|
|
234
|
+
recommendations = []
|
|
235
|
+
|
|
236
|
+
# Analyze patterns
|
|
237
|
+
negative_actions = [
|
|
238
|
+
p["action"] for p in patterns
|
|
239
|
+
if p["score_impact"] < 0
|
|
240
|
+
]
|
|
241
|
+
|
|
242
|
+
# Count frequent negative actions
|
|
243
|
+
action_counts = {}
|
|
244
|
+
for action in negative_actions:
|
|
245
|
+
action_counts[action] = action_counts.get(action, 0) + 1
|
|
246
|
+
|
|
247
|
+
# Recommend blocking frequent negative actions
|
|
248
|
+
for action, count in action_counts.items():
|
|
249
|
+
if count >= 3:
|
|
250
|
+
recommendations.append(
|
|
251
|
+
f"Consider blocking action '{action}' - caused {count} negative impacts"
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
return recommendations
|
|
255
|
+
|
|
256
|
+
def get_anomalies(
|
|
257
|
+
self,
|
|
258
|
+
agent_did: Optional[str] = None,
|
|
259
|
+
since: Optional[datetime] = None,
|
|
260
|
+
) -> list:
|
|
261
|
+
"""Get detected anomalies."""
|
|
262
|
+
anomalies = self._anomalies
|
|
263
|
+
|
|
264
|
+
if agent_did:
|
|
265
|
+
anomalies = [a for a in anomalies if a["agent_did"] == agent_did]
|
|
266
|
+
|
|
267
|
+
if since:
|
|
268
|
+
anomalies = [
|
|
269
|
+
a for a in anomalies
|
|
270
|
+
if datetime.fromisoformat(a["observation"]["timestamp"]) >= since
|
|
271
|
+
]
|
|
272
|
+
|
|
273
|
+
return anomalies
|
|
274
|
+
|
|
275
|
+
def get_learning_summary(self) -> dict:
|
|
276
|
+
"""Get summary of learning state."""
|
|
277
|
+
total_observations = sum(len(p) for p in self._patterns.values())
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
"agents_tracked": len(self._patterns),
|
|
281
|
+
"total_observations": total_observations,
|
|
282
|
+
"anomalies_detected": len(self._anomalies),
|
|
283
|
+
"patterns_per_agent": {
|
|
284
|
+
agent: len(patterns)
|
|
285
|
+
for agent, patterns in self._patterns.items()
|
|
286
|
+
},
|
|
287
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Reward Scoring
|
|
3
|
+
|
|
4
|
+
Multi-dimensional scoring with trust scores and reward signals.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from typing import Optional
|
|
9
|
+
from pydantic import BaseModel, Field
|
|
10
|
+
from enum import Enum
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DimensionType(str, Enum):
|
|
14
|
+
"""The 5 reward dimensions."""
|
|
15
|
+
POLICY_COMPLIANCE = "policy_compliance"
|
|
16
|
+
RESOURCE_EFFICIENCY = "resource_efficiency"
|
|
17
|
+
OUTPUT_QUALITY = "output_quality"
|
|
18
|
+
SECURITY_POSTURE = "security_posture"
|
|
19
|
+
COLLABORATION_HEALTH = "collaboration_health"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RewardSignal(BaseModel):
|
|
23
|
+
"""
|
|
24
|
+
A single reward signal.
|
|
25
|
+
|
|
26
|
+
Signals feed into dimension scores which aggregate to trust scores.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
dimension: DimensionType
|
|
30
|
+
value: float = Field(..., ge=0.0, le=1.0, description="0=bad, 1=good")
|
|
31
|
+
|
|
32
|
+
# Source
|
|
33
|
+
source: str = Field(..., description="Where this signal came from")
|
|
34
|
+
|
|
35
|
+
# Context
|
|
36
|
+
details: Optional[str] = None
|
|
37
|
+
trace_id: Optional[str] = None
|
|
38
|
+
|
|
39
|
+
# Timing
|
|
40
|
+
timestamp: datetime = Field(default_factory=datetime.utcnow)
|
|
41
|
+
|
|
42
|
+
# Weight (for importance)
|
|
43
|
+
weight: float = Field(default=1.0, ge=0.0)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class RewardDimension(BaseModel):
|
|
47
|
+
"""Score for a single dimension."""
|
|
48
|
+
|
|
49
|
+
name: str
|
|
50
|
+
score: float = Field(default=50.0, ge=0.0, le=100.0)
|
|
51
|
+
|
|
52
|
+
# Signal statistics
|
|
53
|
+
signal_count: int = Field(default=0)
|
|
54
|
+
positive_signals: int = Field(default=0)
|
|
55
|
+
negative_signals: int = Field(default=0)
|
|
56
|
+
|
|
57
|
+
# Trend
|
|
58
|
+
previous_score: Optional[float] = None
|
|
59
|
+
trend: str = "stable" # improving, degrading, stable
|
|
60
|
+
|
|
61
|
+
# Last update
|
|
62
|
+
updated_at: datetime = Field(default_factory=datetime.utcnow)
|
|
63
|
+
|
|
64
|
+
def add_signal(self, signal: RewardSignal) -> None:
|
|
65
|
+
"""Add a signal and update score."""
|
|
66
|
+
self.signal_count += 1
|
|
67
|
+
|
|
68
|
+
if signal.value >= 0.5:
|
|
69
|
+
self.positive_signals += 1
|
|
70
|
+
else:
|
|
71
|
+
self.negative_signals += 1
|
|
72
|
+
|
|
73
|
+
# Update score (exponential moving average)
|
|
74
|
+
alpha = 0.1 # Smoothing factor
|
|
75
|
+
self.previous_score = self.score
|
|
76
|
+
self.score = self.score * (1 - alpha) + (signal.value * 100) * alpha
|
|
77
|
+
|
|
78
|
+
# Update trend
|
|
79
|
+
if self.previous_score is not None:
|
|
80
|
+
diff = self.score - self.previous_score
|
|
81
|
+
if diff > 5:
|
|
82
|
+
self.trend = "improving"
|
|
83
|
+
elif diff < -5:
|
|
84
|
+
self.trend = "degrading"
|
|
85
|
+
else:
|
|
86
|
+
self.trend = "stable"
|
|
87
|
+
|
|
88
|
+
self.updated_at = datetime.utcnow()
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class TrustScore(BaseModel):
|
|
92
|
+
"""
|
|
93
|
+
Complete trust score for an agent.
|
|
94
|
+
|
|
95
|
+
Aggregates all dimension scores into a single 0-1000 score.
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
agent_did: str
|
|
99
|
+
|
|
100
|
+
# Total score (0-1000)
|
|
101
|
+
total_score: int = Field(default=500, ge=0, le=1000)
|
|
102
|
+
|
|
103
|
+
# Trust tier
|
|
104
|
+
tier: str = "standard" # verified_partner, trusted, standard, probationary, untrusted
|
|
105
|
+
|
|
106
|
+
# Dimension breakdown
|
|
107
|
+
dimensions: dict[str, RewardDimension] = Field(default_factory=dict)
|
|
108
|
+
|
|
109
|
+
# Timestamps
|
|
110
|
+
calculated_at: datetime = Field(default_factory=datetime.utcnow)
|
|
111
|
+
|
|
112
|
+
# History
|
|
113
|
+
previous_score: Optional[int] = None
|
|
114
|
+
score_change: int = 0
|
|
115
|
+
|
|
116
|
+
model_config = {"validate_assignment": True}
|
|
117
|
+
|
|
118
|
+
def __init__(self, **data):
|
|
119
|
+
super().__init__(**data)
|
|
120
|
+
self._update_tier()
|
|
121
|
+
|
|
122
|
+
def _update_tier(self) -> None:
|
|
123
|
+
"""Update tier based on score."""
|
|
124
|
+
if self.total_score >= 900:
|
|
125
|
+
self.tier = "verified_partner"
|
|
126
|
+
elif self.total_score >= 700:
|
|
127
|
+
self.tier = "trusted"
|
|
128
|
+
elif self.total_score >= 500:
|
|
129
|
+
self.tier = "standard"
|
|
130
|
+
elif self.total_score >= 300:
|
|
131
|
+
self.tier = "probationary"
|
|
132
|
+
else:
|
|
133
|
+
self.tier = "untrusted"
|
|
134
|
+
|
|
135
|
+
def update(self, new_score: int, dimensions: dict[str, RewardDimension]) -> None:
|
|
136
|
+
"""Update the trust score."""
|
|
137
|
+
self.previous_score = self.total_score
|
|
138
|
+
self.total_score = max(0, min(1000, new_score))
|
|
139
|
+
self.score_change = self.total_score - (self.previous_score or 0)
|
|
140
|
+
self.dimensions = dimensions
|
|
141
|
+
self.calculated_at = datetime.utcnow()
|
|
142
|
+
self._update_tier()
|
|
143
|
+
|
|
144
|
+
def meets_threshold(self, threshold: int) -> bool:
|
|
145
|
+
"""Check if score meets a threshold."""
|
|
146
|
+
return self.total_score >= threshold
|
|
147
|
+
|
|
148
|
+
def to_dict(self) -> dict:
|
|
149
|
+
"""Export as dictionary."""
|
|
150
|
+
return {
|
|
151
|
+
"agent_did": self.agent_did,
|
|
152
|
+
"total_score": self.total_score,
|
|
153
|
+
"tier": self.tier,
|
|
154
|
+
"dimensions": {
|
|
155
|
+
name: {
|
|
156
|
+
"score": dim.score,
|
|
157
|
+
"trend": dim.trend,
|
|
158
|
+
"signal_count": dim.signal_count,
|
|
159
|
+
}
|
|
160
|
+
for name, dim in self.dimensions.items()
|
|
161
|
+
},
|
|
162
|
+
"calculated_at": self.calculated_at.isoformat(),
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class ScoreThresholds(BaseModel):
|
|
167
|
+
"""Configurable score thresholds."""
|
|
168
|
+
|
|
169
|
+
# Tier thresholds
|
|
170
|
+
verified_partner: int = 900
|
|
171
|
+
trusted: int = 700
|
|
172
|
+
standard: int = 500
|
|
173
|
+
probationary: int = 300
|
|
174
|
+
|
|
175
|
+
# Action thresholds
|
|
176
|
+
allow_threshold: int = 500
|
|
177
|
+
warn_threshold: int = 400
|
|
178
|
+
revocation_threshold: int = 300
|
|
179
|
+
|
|
180
|
+
def get_tier(self, score: int) -> str:
|
|
181
|
+
"""Get tier for a score."""
|
|
182
|
+
if score >= self.verified_partner:
|
|
183
|
+
return "verified_partner"
|
|
184
|
+
elif score >= self.trusted:
|
|
185
|
+
return "trusted"
|
|
186
|
+
elif score >= self.standard:
|
|
187
|
+
return "standard"
|
|
188
|
+
elif score >= self.probationary:
|
|
189
|
+
return "probationary"
|
|
190
|
+
else:
|
|
191
|
+
return "untrusted"
|
|
192
|
+
|
|
193
|
+
def should_allow(self, score: int) -> bool:
|
|
194
|
+
"""Check if score should allow actions."""
|
|
195
|
+
return score >= self.allow_threshold
|
|
196
|
+
|
|
197
|
+
def should_warn(self, score: int) -> bool:
|
|
198
|
+
"""Check if score should trigger warning."""
|
|
199
|
+
return score < self.warn_threshold
|
|
200
|
+
|
|
201
|
+
def should_revoke(self, score: int) -> bool:
|
|
202
|
+
"""Check if score should trigger revocation."""
|
|
203
|
+
return score < self.revocation_threshold
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Trust & Protocol Bridge (Layer 2)
|
|
3
|
+
|
|
4
|
+
Implements IATP for agent-to-agent trust handshakes.
|
|
5
|
+
Native A2A and MCP support with transparent protocol translation.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .bridge import TrustBridge, ProtocolBridge
|
|
9
|
+
from .handshake import TrustHandshake, HandshakeResult
|
|
10
|
+
from .capability import CapabilityScope, CapabilityGrant
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"TrustBridge",
|
|
14
|
+
"ProtocolBridge",
|
|
15
|
+
"TrustHandshake",
|
|
16
|
+
"HandshakeResult",
|
|
17
|
+
"CapabilityScope",
|
|
18
|
+
"CapabilityGrant",
|
|
19
|
+
]
|