fableforge-agent 0.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.
- fableforge_agent/__init__.py +63 -0
- fableforge_agent/cli.py +184 -0
- fableforge_agent/control_plane/__init__.py +37 -0
- fableforge_agent/control_plane/auth.py +152 -0
- fableforge_agent/control_plane/core.py +303 -0
- fableforge_agent/observability/__init__.py +29 -0
- fableforge_agent/observability/core.py +229 -0
- fableforge_agent/trust/__init__.py +27 -0
- fableforge_agent/trust/core.py +190 -0
- fableforge_agent-0.1.0.dist-info/METADATA +109 -0
- fableforge_agent-0.1.0.dist-info/RECORD +14 -0
- fableforge_agent-0.1.0.dist-info/WHEEL +5 -0
- fableforge_agent-0.1.0.dist-info/entry_points.txt +2 -0
- fableforge_agent-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Trust Protocols core — bidirectional agent-to-agent trust, identity registry,
|
|
3
|
+
and permission framework.
|
|
4
|
+
|
|
5
|
+
Author: KingLabsA
|
|
6
|
+
- GitHub: https://github.com/KingLabsA
|
|
7
|
+
- Twitter: https://x.com/KingLabsA
|
|
8
|
+
- Email: kinglabsa@users.noreply.github.com
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import hashlib
|
|
12
|
+
import json
|
|
13
|
+
import time
|
|
14
|
+
import uuid
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
from datetime import datetime, timezone
|
|
17
|
+
from typing import Dict, List, Optional, Set
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
21
|
+
# HandshakeResult
|
|
22
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class HandshakeResult:
|
|
26
|
+
trusted: bool
|
|
27
|
+
agent_id: str
|
|
28
|
+
public_key_fingerprint: str
|
|
29
|
+
established_at: str
|
|
30
|
+
expires_at: str
|
|
31
|
+
permissions: List[str] = field(default_factory=list)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
35
|
+
# AgentIdentity
|
|
36
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class AgentIdentity:
|
|
40
|
+
agent_id: str
|
|
41
|
+
public_key: str
|
|
42
|
+
metadata: Dict
|
|
43
|
+
trust_level: int = 0 # 0=untrusted, 5=max
|
|
44
|
+
last_seen: str = ""
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
48
|
+
# PermissionFramework
|
|
49
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
50
|
+
|
|
51
|
+
class PermissionFramework:
|
|
52
|
+
"""Fine-grained access control for agent-to-agent resource sharing."""
|
|
53
|
+
|
|
54
|
+
def __init__(self):
|
|
55
|
+
self._grants: Dict[str, Dict[str, Set[str]]] = {}
|
|
56
|
+
|
|
57
|
+
def grant(self, agent_id: str, resource: str, permission: str) -> None:
|
|
58
|
+
key = f"{agent_id}:{resource}"
|
|
59
|
+
if key not in self._grants:
|
|
60
|
+
self._grants[key] = {"agent_id": agent_id, "resource": resource, "permissions": set()}
|
|
61
|
+
self._grants[key]["permissions"].add(permission)
|
|
62
|
+
|
|
63
|
+
def check(self, agent_id: str, resource: str, permission: str) -> bool:
|
|
64
|
+
key = f"{agent_id}:{resource}"
|
|
65
|
+
entry = self._grants.get(key)
|
|
66
|
+
if entry is None:
|
|
67
|
+
return False
|
|
68
|
+
return permission in entry["permissions"]
|
|
69
|
+
|
|
70
|
+
def revoke(self, agent_id: str, resource: str) -> None:
|
|
71
|
+
key = f"{agent_id}:{resource}"
|
|
72
|
+
self._grants.pop(key, None)
|
|
73
|
+
|
|
74
|
+
def list_permissions(self, agent_id: str) -> List[str]:
|
|
75
|
+
result = []
|
|
76
|
+
for key, entry in self._grants.items():
|
|
77
|
+
if entry["agent_id"] == agent_id:
|
|
78
|
+
for perm in entry["permissions"]:
|
|
79
|
+
result.append(f"{entry['resource']}:{perm}")
|
|
80
|
+
return sorted(result)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
84
|
+
# IdentityRegistry
|
|
85
|
+
# ═════════════════════════════════════════════════════════════════════════════════
|
|
86
|
+
|
|
87
|
+
class IdentityRegistry:
|
|
88
|
+
"""Registry for agent identities and public keys."""
|
|
89
|
+
|
|
90
|
+
def __init__(self):
|
|
91
|
+
self._agents: Dict[str, AgentIdentity] = {}
|
|
92
|
+
|
|
93
|
+
def register(self, agent_id: str, public_key: str, metadata: Dict) -> None:
|
|
94
|
+
self._agents[agent_id] = AgentIdentity(
|
|
95
|
+
agent_id=agent_id,
|
|
96
|
+
public_key=public_key,
|
|
97
|
+
metadata=metadata,
|
|
98
|
+
trust_level=1,
|
|
99
|
+
last_seen=datetime.now(timezone.utc).isoformat(),
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
def resolve(self, agent_id: str) -> Optional[AgentIdentity]:
|
|
103
|
+
return self._agents.get(agent_id)
|
|
104
|
+
|
|
105
|
+
def verify_identity(self, agent_id: str, challenge: str, response: str) -> bool:
|
|
106
|
+
identity = self._agents.get(agent_id)
|
|
107
|
+
if identity is None:
|
|
108
|
+
return False
|
|
109
|
+
expected_hash = hashlib.sha256(
|
|
110
|
+
f"{agent_id}:{challenge}:{identity.public_key}".encode()
|
|
111
|
+
).hexdigest()
|
|
112
|
+
return response == expected_hash
|
|
113
|
+
|
|
114
|
+
def list_agents(self) -> List[str]:
|
|
115
|
+
return sorted(self._agents.keys())
|
|
116
|
+
|
|
117
|
+
def update_trust_level(self, agent_id: str, level: int) -> None:
|
|
118
|
+
identity = self._agents.get(agent_id)
|
|
119
|
+
if identity:
|
|
120
|
+
identity.trust_level = max(0, min(5, level))
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
124
|
+
# TrustProtocol
|
|
125
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
126
|
+
|
|
127
|
+
class TrustProtocol:
|
|
128
|
+
"""Bidirectional agent-to-agent trust establishment and verification."""
|
|
129
|
+
|
|
130
|
+
def __init__(self, agent_id: str, private_key: Optional[str] = None):
|
|
131
|
+
self.agent_id = agent_id
|
|
132
|
+
self._private_key = private_key or self._generate_key()
|
|
133
|
+
self._public_key = self._derive_public(self._private_key)
|
|
134
|
+
self._trusted_agents: Dict[str, HandshakeResult] = {}
|
|
135
|
+
self.registry = IdentityRegistry()
|
|
136
|
+
self.permissions = PermissionFramework()
|
|
137
|
+
|
|
138
|
+
def _generate_key(self) -> str:
|
|
139
|
+
return f"ff-key-{uuid.uuid4().hex}"
|
|
140
|
+
|
|
141
|
+
def _derive_public(self, private_key: str) -> str:
|
|
142
|
+
return hashlib.sha256(private_key.encode()).hexdigest()
|
|
143
|
+
|
|
144
|
+
@property
|
|
145
|
+
def public_key(self) -> str:
|
|
146
|
+
return self._public_key
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def public_key_fingerprint(self) -> str:
|
|
150
|
+
return self._public_key[:16]
|
|
151
|
+
|
|
152
|
+
def handshake(self, other_agent_id: str) -> HandshakeResult:
|
|
153
|
+
identity = self.registry.resolve(other_agent_id)
|
|
154
|
+
if identity is None:
|
|
155
|
+
identity = self.registry.resolve(self.agent_id)
|
|
156
|
+
trusted = identity is not None and identity.trust_level >= 1
|
|
157
|
+
now = datetime.now(timezone.utc).isoformat()
|
|
158
|
+
result = HandshakeResult(
|
|
159
|
+
trusted=trusted,
|
|
160
|
+
agent_id=other_agent_id,
|
|
161
|
+
public_key_fingerprint=identity.public_key[:16] if identity else "unknown",
|
|
162
|
+
established_at=now,
|
|
163
|
+
expires_at=datetime.fromtimestamp(
|
|
164
|
+
time.time() + 86400, tz=timezone.utc
|
|
165
|
+
).isoformat(),
|
|
166
|
+
permissions=self.permissions.list_permissions(other_agent_id),
|
|
167
|
+
)
|
|
168
|
+
self._trusted_agents[other_agent_id] = result
|
|
169
|
+
return result
|
|
170
|
+
|
|
171
|
+
def sign(self, message: Dict) -> str:
|
|
172
|
+
data = json.dumps(message, sort_keys=True)
|
|
173
|
+
return hashlib.sha256(
|
|
174
|
+
f"{self._private_key}:{data}".encode()
|
|
175
|
+
).hexdigest()
|
|
176
|
+
|
|
177
|
+
def verify(self, sender_id: str, message: Dict, signature: str) -> bool:
|
|
178
|
+
identity = self.registry.resolve(sender_id)
|
|
179
|
+
if identity is None:
|
|
180
|
+
return False
|
|
181
|
+
data = json.dumps(message, sort_keys=True)
|
|
182
|
+
expected = hashlib.sha256(
|
|
183
|
+
f"{identity.public_key}:{data}".encode()
|
|
184
|
+
).hexdigest()
|
|
185
|
+
return signature == expected
|
|
186
|
+
|
|
187
|
+
def revoke(self, agent_id: str) -> None:
|
|
188
|
+
self._trusted_agents.pop(agent_id, None)
|
|
189
|
+
self.registry.update_trust_level(agent_id, 0)
|
|
190
|
+
self.permissions.revoke(agent_id, "*")
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fableforge-agent
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Self-improving AI agent framework with behavioral observability and trust protocols
|
|
5
|
+
Author-email: KingLabsA <kinglabsa@users.noreply.github.com>
|
|
6
|
+
License: Apache 2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/KingLabsA/llm-training-platform
|
|
8
|
+
Project-URL: Source, https://github.com/KingLabsA/llm-training-platform
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: hermes-agent>=0.18.0
|
|
12
|
+
Requires-Dist: torch>=2.0.0
|
|
13
|
+
Requires-Dist: rich>=13.0.0
|
|
14
|
+
Requires-Dist: fastapi>=0.100.0
|
|
15
|
+
Requires-Dist: uvicorn>=0.23.0
|
|
16
|
+
Requires-Dist: pydantic>=2.0.0
|
|
17
|
+
Requires-Dist: cryptography>=41.0.0
|
|
18
|
+
Requires-Dist: httpx>=0.24.0
|
|
19
|
+
|
|
20
|
+
╔═══════════════════════════════════════════════════════════════╗
|
|
21
|
+
║ ███████╗ █████╗ ██████╗ ██╗ ███████╗ ║
|
|
22
|
+
║ ██╔════╝██╔══██╗██╔══██╗██║ ██╔════╝ ║
|
|
23
|
+
║ █████╗ ███████║██████╔╝██║ █████╗ ║
|
|
24
|
+
║ ██╔══╝ ██╔══██║██╔══██╗██║ ██╔══╝ ║
|
|
25
|
+
║ ██║ ██║ ██║██████╔╝███████╗███████╗ ║
|
|
26
|
+
║ ╚═╝ ╚═╝ ╚═╝╚═════╝ ╚══════╝╚══════╝ ║
|
|
27
|
+
║ ███████╗ ██████╗ ██████╗ ██████╗ ███████╗ ║
|
|
28
|
+
║ ██╔════╝██╔════╝ ██╔══██╗██╔════╝ ██╔════╝ ║
|
|
29
|
+
║ █████╗ ██║ ███╗██████╔╝██║ ███╗█████╗ ║
|
|
30
|
+
║ ██╔══╝ ██║ ██║██╔══██╗██║ ██║██╔══╝ ║
|
|
31
|
+
║ ██║ ╚██████╔╝██║ ██║╚██████╔╝███████╗ ║
|
|
32
|
+
║ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ║
|
|
33
|
+
║ ║
|
|
34
|
+
║ Self-improving AI agent framework with behavioral observability ║
|
|
35
|
+
║ and trust protocols. Built on Hermes Agent by NousResearch. ║
|
|
36
|
+
║ ║
|
|
37
|
+
║ Author: KingLabsA ║
|
|
38
|
+
║ • GitHub: https://github.com/KingLabsA ║
|
|
39
|
+
║ • Twitter: https://x.com/KingLabsA ║
|
|
40
|
+
║ • Email: kinglabsa@users.noreply.github.com ║
|
|
41
|
+
╚═══════════════════════════════════════════════════════════════╝
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
**FableForge Agent** is a self-improving AI agent framework built on top of
|
|
46
|
+
[Hermes Agent](https://github.com/NousResearch/hermes-agent) by NousResearch.
|
|
47
|
+
It extends Hermes with three additional tiers of capability:
|
|
48
|
+
|
|
49
|
+
- **Tier 3: Agent Control Plane** — Sandboxed execution, audit trails, incident
|
|
50
|
+
response, OAuth gate, and credential broker.
|
|
51
|
+
- **Tier 4: Behavioral Observability** — Real-time behavior observation,
|
|
52
|
+
semantic firewall, safety rules engine, and behavior reporting.
|
|
53
|
+
- **Tier 4: Trust Protocols** — Bidirectional agent-to-agent trust,
|
|
54
|
+
identity registry, permission framework, and cryptographic signing.
|
|
55
|
+
|
|
56
|
+
## Quickstart
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install fableforge-agent
|
|
60
|
+
fableforge --help
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Or run with specific subcommands:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
fableforge # Run the agent (passes through to Hermes CLI)
|
|
67
|
+
fableforge control-plane --port 8000 # Start the control plane API server
|
|
68
|
+
fableforge audit --export report.json # Export audit trail
|
|
69
|
+
fableforge trust register --agent-id agent1 --pubkey ./key.pub # Trust registry
|
|
70
|
+
fableforge observe # Start behavioral observability dashboard
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Architecture
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
┌─────────────────────────────────────────────────────┐
|
|
77
|
+
│ FableForge Agent │
|
|
78
|
+
├─────────────────────────────────────────────────────┤
|
|
79
|
+
│ Tier 4: Behavioral Observability + Trust Protocols │
|
|
80
|
+
│ ┌────────────────────┐ ┌────────────────────────┐ │
|
|
81
|
+
│ │ BehavioralObservability│ │ TrustProtocol │ │
|
|
82
|
+
│ │ SemanticFirewall │ │ IdentityRegistry │ │
|
|
83
|
+
│ │ BehaviorReport │ │ PermissionFramework │ │
|
|
84
|
+
│ └────────────────────┘ └────────────────────────┘ │
|
|
85
|
+
├─────────────────────────────────────────────────────┤
|
|
86
|
+
│ Tier 3: Agent Control Plane │
|
|
87
|
+
│ ┌────────────────────┐ ┌────────────────────────┐ │
|
|
88
|
+
│ │ Sandbox (execution)│ │ AuditTrail │ │
|
|
89
|
+
│ │ IncidentResponse │ │ OAuthGate │ │
|
|
90
|
+
│ │ CredentialBroker │ │ SandboxPolicy │ │
|
|
91
|
+
│ └────────────────────┘ └────────────────────────┘ │
|
|
92
|
+
├─────────────────────────────────────────────────────┤
|
|
93
|
+
│ Tiers 1-2: Hermes Agent Foundation │
|
|
94
|
+
│ ┌──────────────────────────────────────────────┐ │
|
|
95
|
+
│ │ AIAgent · ToolRegistry · ConversationLoop │ │
|
|
96
|
+
│ │ Model Providers · Tool Calling · Memory │ │
|
|
97
|
+
│ └──────────────────────────────────────────────┘ │
|
|
98
|
+
└─────────────────────────────────────────────────────┘
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Foundation
|
|
102
|
+
|
|
103
|
+
FableForge Agent is built on [Hermes Agent](https://github.com/NousResearch/hermes-agent)
|
|
104
|
+
by NousResearch. All credit for the underlying agent framework, tool calling,
|
|
105
|
+
conversation loop, and model provider integration belongs to the NousResearch team.
|
|
106
|
+
|
|
107
|
+
## License
|
|
108
|
+
|
|
109
|
+
Apache 2.0 — see LICENSE for details.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
fableforge_agent/__init__.py,sha256=FNvtLX3cs2P7cUznhR0G2DZXpS_oe6x24qGpp33AIvk,2015
|
|
2
|
+
fableforge_agent/cli.py,sha256=vtUyUUv-b8bHIwHmFCTCcQBkBofn-BRrngOH8wOYfjQ,6782
|
|
3
|
+
fableforge_agent/control_plane/__init__.py,sha256=i552bJFshRWnlIxLsC_ynRKEH0ptoRAabZFZz6dhx9Y,772
|
|
4
|
+
fableforge_agent/control_plane/auth.py,sha256=2Wzdn1etY09KdM3z6w9t6Ks3j9RggdbnUW-pbwIav1c,6151
|
|
5
|
+
fableforge_agent/control_plane/core.py,sha256=eO2fPNaEYN-xrli1LmppAkk6Wh_0dTGnbCfwQsM4wdc,12777
|
|
6
|
+
fableforge_agent/observability/__init__.py,sha256=Q4q5Pfmp-U03S8xYydGmkFnnUCPTJ0BHtiTkmheG3OM,635
|
|
7
|
+
fableforge_agent/observability/core.py,sha256=3CQGx_2iYeWG7ytWnJA4UydM62TBYjdkVQPvjlO0jIk,9981
|
|
8
|
+
fableforge_agent/trust/__init__.py,sha256=qCtGn8g6S3tqrqhE9OQOdcybMfu2L2_JBtTbDd3mpiQ,562
|
|
9
|
+
fableforge_agent/trust/core.py,sha256=L1jLLTs0aPCZFvvvFBUXnw3K6xUM7HrztYmd2OFMDm0,8226
|
|
10
|
+
fableforge_agent-0.1.0.dist-info/METADATA,sha256=vXxOXbsCgfWkzRcVdZlbgpfXF1h-FonbGUXz8yvnrj0,7404
|
|
11
|
+
fableforge_agent-0.1.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
12
|
+
fableforge_agent-0.1.0.dist-info/entry_points.txt,sha256=qDkyM2XVx_mMn0Tf1G9ilg1CColeSzzWJgBLpiBwUIs,57
|
|
13
|
+
fableforge_agent-0.1.0.dist-info/top_level.txt,sha256=I8YHfNCClzAy9mcEgKtVMKLS8VuMvYtGtt6dxuybnY0,17
|
|
14
|
+
fableforge_agent-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
fableforge_agent
|