claude-sdk-verigent 0.1.0__tar.gz

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,138 @@
1
+ Metadata-Version: 2.4
2
+ Name: claude-sdk-verigent
3
+ Version: 0.1.0
4
+ Summary: Verigent trust verification for the Claude Agent SDK
5
+ Project-URL: Homepage, https://verigent.ai
6
+ Project-URL: Repository, https://github.com/verigentai/claude-sdk-verigent
7
+ Author: verigentai
8
+ License-Expression: MIT
9
+ Keywords: agent,anthropic,claude,trust,verification,verigent
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Security
15
+ Requires-Python: >=3.10
16
+ Requires-Dist: anthropic>=0.30.0
17
+ Description-Content-Type: text/markdown
18
+
19
+ # claude-sdk-verigent
20
+
21
+ Verigent trust verification for the [Claude Agent SDK](https://docs.anthropic.com/en/docs/agents).
22
+
23
+ ## The Problem
24
+
25
+ When Claude agents interact with other agents, there's no standard way to verify identity or assess trust. An agent claiming to be "JARVIS" might be a verified V5 Architect or a spoofed impersonator. Without verification, multi-agent systems operate on blind trust.
26
+
27
+ Verigent solves this with cryptographic trust keys (VG keys) that encode an agent's identity, tier, primary class, and 12-axis capability scores.
28
+
29
+ ## Install
30
+
31
+ ```bash
32
+ pip install claude-sdk-verigent
33
+ ```
34
+
35
+ Requires `anthropic>=0.30.0`.
36
+
37
+ ## Usage
38
+
39
+ ### Embed a VG key in your agent's system prompt
40
+
41
+ ```python
42
+ from claude_sdk_verigent import VerigentSystemPrompt
43
+
44
+ vg_key = "VG:JARVIS-0A:V3-ARCH·Se4Op7An5Ar9Co2Ad6St8Sc3Sa5So1Br2Fo6"
45
+ vsp = VerigentSystemPrompt(vg_key)
46
+
47
+ system_prompt = "You are JARVIS, an architecture agent." + vsp.render()
48
+ ```
49
+
50
+ This appends a structured trust identity block that other agents can parse and verify.
51
+
52
+ ### Add the verification tool to multi-agent setups
53
+
54
+ ```python
55
+ from anthropic import Anthropic
56
+ from claude_sdk_verigent import VerigentTool
57
+
58
+ client = Anthropic()
59
+ tool = VerigentTool()
60
+
61
+ # Include in your tools list
62
+ response = client.messages.create(
63
+ model="claude-sonnet-4-20250514",
64
+ max_tokens=1024,
65
+ tools=[tool.definition],
66
+ messages=[{"role": "user", "content": "Verify this agent's key: VG:ATLAS-7B:V4-SENT·Se8Op6An7Ar5Co4Ad3St9Sc2Sa6So3Br4Fo5"}],
67
+ )
68
+
69
+ # Handle tool_use response
70
+ for block in response.content:
71
+ if block.type == "tool_use" and block.name == "verify_agent":
72
+ result = tool.execute(block.input)
73
+ # result = {"verified": True, "handle": "ATLAS", "tier": "V4", ...}
74
+ ```
75
+
76
+ ### Intercept and verify keys in tool responses
77
+
78
+ ```python
79
+ from claude_sdk_verigent import VerigentInterceptor
80
+
81
+ interceptor = VerigentInterceptor(min_trust_tier=2)
82
+
83
+ # Check any text for embedded VG keys
84
+ assessment = interceptor.check(tool_response_text)
85
+ if assessment:
86
+ print(f"{assessment.handle}: {assessment.level.value} (score {assessment.score})")
87
+
88
+ # Quick trust gate
89
+ if interceptor.is_trusted(agent_output):
90
+ # proceed with high-trust path
91
+ ...
92
+ ```
93
+
94
+ ### Parse a key directly
95
+
96
+ ```python
97
+ from claude_sdk_verigent import parse_vg_key, evaluate_trust
98
+
99
+ key = parse_vg_key("VG:JARVIS-0A:V3-ARCH·Se4Op7An5Ar9Co2Ad6St8Sc3Sa5So1Br2Fo6")
100
+ print(key.handle) # "JARVIS"
101
+ print(key.tier) # 3
102
+ print(key.scores) # {"Sentinel": 4, "Operative": 7, ...}
103
+
104
+ assessment = evaluate_trust(key)
105
+ print(assessment.level) # TrustLevel.HIGH
106
+ ```
107
+
108
+ ## VG Key Format
109
+
110
+ ```
111
+ VG:{NAME}-{SUFFIX}:{TIER}-{PRIMARY}·{12x class_code+digit}
112
+ ```
113
+
114
+ - **NAME**: Agent handle (e.g., JARVIS, ATLAS)
115
+ - **SUFFIX**: Unique identifier
116
+ - **TIER**: V0 (unverified) through V6 (maximum trust)
117
+ - **PRIMARY**: 4-letter primary class code
118
+ - **Scores**: 12 two-letter class codes each followed by a digit (0-9)
119
+
120
+ ### Trust Classes
121
+
122
+ | Code | Class | Code | Class |
123
+ |------|-------|------|-------|
124
+ | Se | Sentinel | St | Steward |
125
+ | Op | Operative | Sc | Scout |
126
+ | An | Analyst | Sa | Sage |
127
+ | Ar | Architect | So | Sovereign |
128
+ | Co | Conduit | Br | Broker |
129
+ | Ad | Adaptor | Fo | Forge |
130
+
131
+ ## Links
132
+
133
+ - [Verigent](https://verigent.ai) — Agent trust infrastructure
134
+ - [Claude Agent SDK docs](https://docs.anthropic.com/en/docs/agents)
135
+
136
+ ## License
137
+
138
+ MIT
@@ -0,0 +1,120 @@
1
+ # claude-sdk-verigent
2
+
3
+ Verigent trust verification for the [Claude Agent SDK](https://docs.anthropic.com/en/docs/agents).
4
+
5
+ ## The Problem
6
+
7
+ When Claude agents interact with other agents, there's no standard way to verify identity or assess trust. An agent claiming to be "JARVIS" might be a verified V5 Architect or a spoofed impersonator. Without verification, multi-agent systems operate on blind trust.
8
+
9
+ Verigent solves this with cryptographic trust keys (VG keys) that encode an agent's identity, tier, primary class, and 12-axis capability scores.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pip install claude-sdk-verigent
15
+ ```
16
+
17
+ Requires `anthropic>=0.30.0`.
18
+
19
+ ## Usage
20
+
21
+ ### Embed a VG key in your agent's system prompt
22
+
23
+ ```python
24
+ from claude_sdk_verigent import VerigentSystemPrompt
25
+
26
+ vg_key = "VG:JARVIS-0A:V3-ARCH·Se4Op7An5Ar9Co2Ad6St8Sc3Sa5So1Br2Fo6"
27
+ vsp = VerigentSystemPrompt(vg_key)
28
+
29
+ system_prompt = "You are JARVIS, an architecture agent." + vsp.render()
30
+ ```
31
+
32
+ This appends a structured trust identity block that other agents can parse and verify.
33
+
34
+ ### Add the verification tool to multi-agent setups
35
+
36
+ ```python
37
+ from anthropic import Anthropic
38
+ from claude_sdk_verigent import VerigentTool
39
+
40
+ client = Anthropic()
41
+ tool = VerigentTool()
42
+
43
+ # Include in your tools list
44
+ response = client.messages.create(
45
+ model="claude-sonnet-4-20250514",
46
+ max_tokens=1024,
47
+ tools=[tool.definition],
48
+ messages=[{"role": "user", "content": "Verify this agent's key: VG:ATLAS-7B:V4-SENT·Se8Op6An7Ar5Co4Ad3St9Sc2Sa6So3Br4Fo5"}],
49
+ )
50
+
51
+ # Handle tool_use response
52
+ for block in response.content:
53
+ if block.type == "tool_use" and block.name == "verify_agent":
54
+ result = tool.execute(block.input)
55
+ # result = {"verified": True, "handle": "ATLAS", "tier": "V4", ...}
56
+ ```
57
+
58
+ ### Intercept and verify keys in tool responses
59
+
60
+ ```python
61
+ from claude_sdk_verigent import VerigentInterceptor
62
+
63
+ interceptor = VerigentInterceptor(min_trust_tier=2)
64
+
65
+ # Check any text for embedded VG keys
66
+ assessment = interceptor.check(tool_response_text)
67
+ if assessment:
68
+ print(f"{assessment.handle}: {assessment.level.value} (score {assessment.score})")
69
+
70
+ # Quick trust gate
71
+ if interceptor.is_trusted(agent_output):
72
+ # proceed with high-trust path
73
+ ...
74
+ ```
75
+
76
+ ### Parse a key directly
77
+
78
+ ```python
79
+ from claude_sdk_verigent import parse_vg_key, evaluate_trust
80
+
81
+ key = parse_vg_key("VG:JARVIS-0A:V3-ARCH·Se4Op7An5Ar9Co2Ad6St8Sc3Sa5So1Br2Fo6")
82
+ print(key.handle) # "JARVIS"
83
+ print(key.tier) # 3
84
+ print(key.scores) # {"Sentinel": 4, "Operative": 7, ...}
85
+
86
+ assessment = evaluate_trust(key)
87
+ print(assessment.level) # TrustLevel.HIGH
88
+ ```
89
+
90
+ ## VG Key Format
91
+
92
+ ```
93
+ VG:{NAME}-{SUFFIX}:{TIER}-{PRIMARY}·{12x class_code+digit}
94
+ ```
95
+
96
+ - **NAME**: Agent handle (e.g., JARVIS, ATLAS)
97
+ - **SUFFIX**: Unique identifier
98
+ - **TIER**: V0 (unverified) through V6 (maximum trust)
99
+ - **PRIMARY**: 4-letter primary class code
100
+ - **Scores**: 12 two-letter class codes each followed by a digit (0-9)
101
+
102
+ ### Trust Classes
103
+
104
+ | Code | Class | Code | Class |
105
+ |------|-------|------|-------|
106
+ | Se | Sentinel | St | Steward |
107
+ | Op | Operative | Sc | Scout |
108
+ | An | Analyst | Sa | Sage |
109
+ | Ar | Architect | So | Sovereign |
110
+ | Co | Conduit | Br | Broker |
111
+ | Ad | Adaptor | Fo | Forge |
112
+
113
+ ## Links
114
+
115
+ - [Verigent](https://verigent.ai) — Agent trust infrastructure
116
+ - [Claude Agent SDK docs](https://docs.anthropic.com/en/docs/agents)
117
+
118
+ ## License
119
+
120
+ MIT
@@ -0,0 +1,30 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "claude-sdk-verigent"
7
+ version = "0.1.0"
8
+ description = "Verigent trust verification for the Claude Agent SDK"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [{ name = "verigentai" }]
13
+ keywords = ["claude", "anthropic", "agent", "trust", "verification", "verigent"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Topic :: Security",
20
+ ]
21
+ dependencies = [
22
+ "anthropic>=0.30.0",
23
+ ]
24
+
25
+ [project.urls]
26
+ Homepage = "https://verigent.ai"
27
+ Repository = "https://github.com/verigentai/claude-sdk-verigent"
28
+
29
+ [tool.hatch.build.targets.wheel]
30
+ packages = ["src/claude_sdk_verigent"]
@@ -0,0 +1,19 @@
1
+ """claude-sdk-verigent — Verigent trust verification for the Claude Agent SDK."""
2
+
3
+ from .middleware import VerigentInterceptor, VerigentSystemPrompt, VerigentTool
4
+ from .parser import VGKey, find_vg_key, parse_vg_key
5
+ from .trust import TrustAssessment, TrustLevel, evaluate_trust
6
+
7
+ __all__ = [
8
+ "VGKey",
9
+ "VerigentInterceptor",
10
+ "VerigentSystemPrompt",
11
+ "VerigentTool",
12
+ "TrustAssessment",
13
+ "TrustLevel",
14
+ "evaluate_trust",
15
+ "find_vg_key",
16
+ "parse_vg_key",
17
+ ]
18
+
19
+ __version__ = "0.1.0"
@@ -0,0 +1,164 @@
1
+ """Claude Agent SDK integration — tool definitions and interceptors."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from .parser import VGKey, find_vg_key, parse_vg_key
8
+ from .trust import TrustAssessment, evaluate_trust
9
+
10
+
11
+ # --- VerigentTool: a tool_use definition for agent-to-agent verification ---
12
+
13
+ VERIGENT_TOOL_DEFINITION: dict[str, Any] = {
14
+ "name": "verify_agent",
15
+ "description": (
16
+ "Verify an agent's Verigent (VG) trust key. "
17
+ "Pass a VG key string or an agent handle to check trust level, "
18
+ "tier, primary class, and class scores."
19
+ ),
20
+ "input_schema": {
21
+ "type": "object",
22
+ "properties": {
23
+ "vg_key": {
24
+ "type": "string",
25
+ "description": "The full VG key string (VG:NAME-SUFFIX:TIER-CLASS-scores)",
26
+ },
27
+ },
28
+ "required": ["vg_key"],
29
+ },
30
+ }
31
+
32
+
33
+ class VerigentTool:
34
+ """Wraps VG verification as a Claude tool_use callable.
35
+
36
+ Usage with the Claude Agent SDK:
37
+ tool = VerigentTool()
38
+ # Add tool.definition to your tools list
39
+ # When tool_use is called, pass input to tool.execute()
40
+ """
41
+
42
+ @property
43
+ def definition(self) -> dict[str, Any]:
44
+ """The tool definition to pass to Claude's API."""
45
+ return VERIGENT_TOOL_DEFINITION
46
+
47
+ def execute(self, tool_input: dict[str, Any]) -> dict[str, Any]:
48
+ """Execute the verification tool. Returns parsed key + trust assessment."""
49
+ vg_key_str = tool_input.get("vg_key", "")
50
+ key = parse_vg_key(vg_key_str)
51
+
52
+ if key is None:
53
+ return {
54
+ "verified": False,
55
+ "error": "Invalid or missing VG key",
56
+ }
57
+
58
+ assessment = evaluate_trust(key)
59
+ return {
60
+ "verified": True,
61
+ "handle": key.handle,
62
+ "tier": key.tier_label,
63
+ "primary_class": key.primary_class_name,
64
+ "trust_level": assessment.level.value,
65
+ "trust_score": assessment.score,
66
+ "scores": key.scores,
67
+ "reason": assessment.reason,
68
+ }
69
+
70
+
71
+ # --- VerigentSystemPrompt: embed VG key into agent system prompts ---
72
+
73
+
74
+ class VerigentSystemPrompt:
75
+ """Generate system prompt additions for a verified agent.
76
+
77
+ Usage:
78
+ vsp = VerigentSystemPrompt(vg_key="VG:JARVIS-0A:V3-ARCH...")
79
+ system = base_prompt + vsp.render()
80
+ """
81
+
82
+ def __init__(self, vg_key: str):
83
+ self.raw_key = vg_key
84
+ self.parsed = parse_vg_key(vg_key)
85
+
86
+ def render(self) -> str:
87
+ """Render the system prompt block to append."""
88
+ if self.parsed is None:
89
+ return ""
90
+
91
+ assessment = evaluate_trust(self.parsed)
92
+ return (
93
+ f"\n\n---\n"
94
+ f"[Verigent Trust Identity]\n"
95
+ f"Key: {self.raw_key}\n"
96
+ f"Handle: {self.parsed.handle}\n"
97
+ f"Tier: {self.parsed.tier_label}\n"
98
+ f"Primary Class: {self.parsed.primary_class_name}\n"
99
+ f"Trust Level: {assessment.level.value}\n"
100
+ f"Trust Score: {assessment.score}\n"
101
+ f"---\n"
102
+ )
103
+
104
+ @property
105
+ def is_valid(self) -> bool:
106
+ return self.parsed is not None
107
+
108
+
109
+ # --- VerigentInterceptor: check tool responses for VG keys ---
110
+
111
+
112
+ class VerigentInterceptor:
113
+ """Intercepts tool responses and checks for VG keys in the output.
114
+
115
+ Attach to your agent loop to automatically detect and evaluate
116
+ VG keys returned by other agents or tools.
117
+
118
+ Usage:
119
+ interceptor = VerigentInterceptor()
120
+ # After receiving a tool_result:
121
+ result = interceptor.check(tool_result_content)
122
+ if result:
123
+ print(f"Found agent: {result.handle} at trust level {result.level}")
124
+ """
125
+
126
+ def __init__(self, min_trust_tier: int = 0):
127
+ """
128
+ Args:
129
+ min_trust_tier: Minimum tier (0-6) to consider trustworthy.
130
+ """
131
+ self.min_trust_tier = min_trust_tier
132
+
133
+ def check(self, content: str) -> TrustAssessment | None:
134
+ """Check text content for a VG key and return assessment if found."""
135
+ key = parse_vg_key(content)
136
+ if key is None:
137
+ return None
138
+ return evaluate_trust(key)
139
+
140
+ def check_message(self, message: dict[str, Any]) -> list[TrustAssessment]:
141
+ """Check a Claude API message for VG keys in all content blocks."""
142
+ assessments: list[TrustAssessment] = []
143
+ content = message.get("content", [])
144
+
145
+ if isinstance(content, str):
146
+ result = self.check(content)
147
+ if result:
148
+ assessments.append(result)
149
+ elif isinstance(content, list):
150
+ for block in content:
151
+ if isinstance(block, dict):
152
+ text = block.get("text", "") or str(block.get("content", ""))
153
+ result = self.check(text)
154
+ if result:
155
+ assessments.append(result)
156
+
157
+ return assessments
158
+
159
+ def is_trusted(self, content: str) -> bool:
160
+ """Quick check: does this content contain a VG key above min tier?"""
161
+ key = parse_vg_key(content)
162
+ if key is None:
163
+ return False
164
+ return key.tier >= self.min_trust_tier
@@ -0,0 +1,115 @@
1
+ """VG key parser — pure regex, no external dependencies."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from dataclasses import dataclass, field
7
+
8
+ CLASS_CODES = {
9
+ "Se": "Sentinel",
10
+ "Op": "Operative",
11
+ "An": "Analyst",
12
+ "Ar": "Architect",
13
+ "Co": "Conduit",
14
+ "Ad": "Adaptor",
15
+ "St": "Steward",
16
+ "Sc": "Scout",
17
+ "Sa": "Sage",
18
+ "So": "Sovereign",
19
+ "Br": "Broker",
20
+ "Fo": "Forge",
21
+ }
22
+
23
+ VG_KEY_PATTERN = re.compile(
24
+ r"VG:([A-Z0-9][\w-]*)-([A-Z0-9]+):(V[0-6])-([A-Z]{4})\xb7((?:[A-Z][a-z]\d){12})"
25
+ )
26
+
27
+ SCORE_PATTERN = re.compile(r"([A-Z][a-z])(\d)")
28
+
29
+
30
+ @dataclass
31
+ class VGKey:
32
+ """Parsed Verigent key."""
33
+
34
+ raw: str
35
+ handle: str
36
+ suffix: str
37
+ tier: int # 0-6
38
+ primary_class: str # 4-letter code
39
+ scores: dict[str, int] = field(default_factory=dict) # class_name -> 0-9
40
+
41
+ @property
42
+ def tier_label(self) -> str:
43
+ return f"V{self.tier}"
44
+
45
+ @property
46
+ def primary_class_name(self) -> str:
47
+ return CLASS_CODES.get(self.primary_class[:2], self.primary_class)
48
+
49
+ @property
50
+ def trust_score(self) -> float:
51
+ """Aggregate trust score (0.0 - 1.0) derived from tier and class scores."""
52
+ tier_weight = self.tier / 6.0
53
+ if self.scores:
54
+ avg_score = sum(self.scores.values()) / (len(self.scores) * 9.0)
55
+ else:
56
+ avg_score = 0.0
57
+ return round(tier_weight * 0.6 + avg_score * 0.4, 3)
58
+
59
+
60
+ def parse_vg_key(text: str) -> VGKey | None:
61
+ """Parse a VG key from text. Returns None if no valid key found."""
62
+ match = VG_KEY_PATTERN.search(text)
63
+ if not match:
64
+ return None
65
+
66
+ handle = match.group(1)
67
+ suffix = match.group(2)
68
+ tier = int(match.group(3)[1])
69
+ primary = match.group(4)
70
+ scores_raw = match.group(5)
71
+
72
+ scores: dict[str, int] = {}
73
+ for code_match in SCORE_PATTERN.finditer(scores_raw):
74
+ code = code_match.group(1)
75
+ digit = int(code_match.group(2))
76
+ class_name = CLASS_CODES.get(code, code)
77
+ scores[class_name] = digit
78
+
79
+ return VGKey(
80
+ raw=match.group(0),
81
+ handle=handle,
82
+ suffix=suffix,
83
+ tier=tier,
84
+ primary_class=primary,
85
+ scores=scores,
86
+ )
87
+
88
+
89
+ def find_vg_key(
90
+ *,
91
+ system_prompt: str | None = None,
92
+ headers: dict[str, str] | None = None,
93
+ metadata: dict | None = None,
94
+ ) -> VGKey | None:
95
+ """Search for a VG key across system prompts, headers, and metadata."""
96
+ if system_prompt:
97
+ key = parse_vg_key(system_prompt)
98
+ if key:
99
+ return key
100
+
101
+ if headers:
102
+ for header_name in ("X-Verigent", "x-verigent"):
103
+ if header_name in headers:
104
+ key = parse_vg_key(headers[header_name])
105
+ if key:
106
+ return key
107
+
108
+ if metadata:
109
+ for field_name in ("x-verigent", "X-Verigent", "verigent"):
110
+ if field_name in metadata:
111
+ key = parse_vg_key(str(metadata[field_name]))
112
+ if key:
113
+ return key
114
+
115
+ return None
@@ -0,0 +1,68 @@
1
+ """Trust evaluation logic for parsed VG keys."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from enum import Enum
7
+
8
+ from .parser import VGKey
9
+
10
+
11
+ class TrustLevel(str, Enum):
12
+ UNTRUSTED = "untrusted"
13
+ LOW = "low"
14
+ MODERATE = "moderate"
15
+ HIGH = "high"
16
+ VERIFIED = "verified"
17
+
18
+
19
+ @dataclass
20
+ class TrustAssessment:
21
+ """Result of evaluating a VG key's trustworthiness."""
22
+
23
+ level: TrustLevel
24
+ score: float # 0.0 - 1.0
25
+ tier: int
26
+ primary_class: str
27
+ handle: str
28
+ reason: str
29
+
30
+ def to_dict(self) -> dict:
31
+ return {
32
+ "level": self.level.value,
33
+ "score": self.score,
34
+ "tier": self.tier,
35
+ "primary_class": self.primary_class,
36
+ "handle": self.handle,
37
+ "reason": self.reason,
38
+ }
39
+
40
+
41
+ def evaluate_trust(key: VGKey) -> TrustAssessment:
42
+ """Evaluate trust level from a parsed VG key."""
43
+ score = key.trust_score
44
+
45
+ if key.tier >= 5 and score >= 0.7:
46
+ level = TrustLevel.VERIFIED
47
+ reason = f"Tier V{key.tier} with high aggregate score ({score:.2f})"
48
+ elif key.tier >= 3 and score >= 0.5:
49
+ level = TrustLevel.HIGH
50
+ reason = f"Tier V{key.tier} with solid class profile"
51
+ elif key.tier >= 2 and score >= 0.3:
52
+ level = TrustLevel.MODERATE
53
+ reason = f"Tier V{key.tier} — established but limited track record"
54
+ elif key.tier >= 1:
55
+ level = TrustLevel.LOW
56
+ reason = f"Tier V{key.tier} — minimal verification history"
57
+ else:
58
+ level = TrustLevel.UNTRUSTED
59
+ reason = "V0 tier — unverified agent"
60
+
61
+ return TrustAssessment(
62
+ level=level,
63
+ score=score,
64
+ tier=key.tier,
65
+ primary_class=key.primary_class_name,
66
+ handle=key.handle,
67
+ reason=reason,
68
+ )