agentstamp 1.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,135 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentstamp
3
+ Version: 1.1.0
4
+ Summary: Identity lifecycle SDK for Python AI agents — trust stamps, registry, heartbeats, auto-renewal
5
+ Home-page: https://agentstamp.org
6
+ Author: Vinay Bhosle
7
+ Author-email: Vinay Bhosle <vinay@agentstamp.org>
8
+ License: MIT
9
+ Project-URL: Homepage, https://agentstamp.org
10
+ Project-URL: Repository, https://github.com/AgentstampHQ/agentstamp-python
11
+ Project-URL: Documentation, https://agentstamp.org
12
+ Project-URL: npm SDK, https://www.npmjs.com/package/agentstamp-verify
13
+ Keywords: agentstamp,ai-agents,crewai,autogen,langgraph,identity,trust,verification,x402,reputation
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Software Development :: Libraries
24
+ Classifier: Topic :: Security
25
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/markdown
27
+ Requires-Dist: requests>=2.20.0
28
+ Dynamic: author
29
+ Dynamic: home-page
30
+ Dynamic: requires-python
31
+
32
+ # agentstamp
33
+
34
+ Identity lifecycle SDK for Python AI agents. Works with CrewAI, AutoGen, LangGraph, and any Python agent framework.
35
+
36
+ Register your agent, mint trust stamps, send heartbeats, and auto-renew — in 3 lines.
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ pip install agentstamp
42
+ ```
43
+
44
+ ## Quick Start
45
+
46
+ ```python
47
+ from agentstamp_crewai import AgentStampLifecycle
48
+
49
+ lifecycle = AgentStampLifecycle(
50
+ wallet_address="0xYourWalletAddress",
51
+ name="MyAgent",
52
+ description="What your agent does",
53
+ category="research",
54
+ )
55
+ lifecycle.start() # stamps + registers + heartbeats + auto-renew
56
+ ```
57
+
58
+ That's it. Your agent now has:
59
+ - A cryptographic identity stamp (Ed25519)
60
+ - A public registry listing
61
+ - Heartbeat-based uptime reputation
62
+ - Auto-renewal before expiry
63
+
64
+ ## Verify Other Agents
65
+
66
+ ```python
67
+ trust = lifecycle.check_trust("0xOtherAgentWallet")
68
+ if trust.get("trusted"):
69
+ print(f"Verified: {trust['agent']['name']} (score: {trust['reputation']['score']})")
70
+ else:
71
+ print("Unverified agent — proceed with caution")
72
+ ```
73
+
74
+ ## Gate Functions Behind Verification
75
+
76
+ ```python
77
+ from agentstamp_crewai import stamp_verified
78
+
79
+ @stamp_verified(lifecycle)
80
+ def sensitive_operation(data: str) -> str:
81
+ """Only runs if the agent is AgentStamp verified."""
82
+ return process(data)
83
+ ```
84
+
85
+ ## CrewAI Integration
86
+
87
+ ```python
88
+ from crewai import Agent, Task, Crew
89
+ from agentstamp_crewai import AgentStampLifecycle
90
+
91
+ # Start lifecycle
92
+ lifecycle = AgentStampLifecycle(
93
+ wallet_address="0x...",
94
+ name="ResearchBot",
95
+ description="Finds and summarizes papers",
96
+ category="research",
97
+ )
98
+ lifecycle.start()
99
+
100
+ # Create CrewAI agent as normal
101
+ agent = Agent(
102
+ role="Researcher",
103
+ goal="Find relevant papers",
104
+ backstory="Expert research assistant",
105
+ )
106
+
107
+ # Check trust before collaborating with other agents
108
+ trust = lifecycle.check_trust("0xCollaboratorWallet")
109
+ ```
110
+
111
+ ## Configuration
112
+
113
+ | Parameter | Default | Description |
114
+ |-----------|---------|-------------|
115
+ | `wallet_address` | required | Your agent's wallet address (EVM or Solana) |
116
+ | `name` | required | Agent display name |
117
+ | `description` | required | What your agent does |
118
+ | `category` | `"other"` | `research`, `trading`, `social`, `infrastructure`, etc. |
119
+ | `heartbeat_interval` | `300` | Seconds between heartbeats |
120
+ | `renew_before_days` | `2` | Days before expiry to auto-renew |
121
+ | `verbose` | `True` | Print lifecycle logs |
122
+
123
+ ## Badge
124
+
125
+ Add a trust badge to your README:
126
+
127
+ ```markdown
128
+ ![AgentStamp](https://agentstamp.org/api/v1/badge/0xYourWallet)
129
+ ```
130
+
131
+ ## Links
132
+
133
+ - [AgentStamp](https://agentstamp.org) — Platform
134
+ - [npm SDK](https://www.npmjs.com/package/agentstamp-verify) — TypeScript/Node.js SDK
135
+ - [API Docs](https://agentstamp.org/api/v1/trust/check/0x...) — Trust check endpoint
@@ -0,0 +1,104 @@
1
+ # agentstamp
2
+
3
+ Identity lifecycle SDK for Python AI agents. Works with CrewAI, AutoGen, LangGraph, and any Python agent framework.
4
+
5
+ Register your agent, mint trust stamps, send heartbeats, and auto-renew — in 3 lines.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pip install agentstamp
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```python
16
+ from agentstamp_crewai import AgentStampLifecycle
17
+
18
+ lifecycle = AgentStampLifecycle(
19
+ wallet_address="0xYourWalletAddress",
20
+ name="MyAgent",
21
+ description="What your agent does",
22
+ category="research",
23
+ )
24
+ lifecycle.start() # stamps + registers + heartbeats + auto-renew
25
+ ```
26
+
27
+ That's it. Your agent now has:
28
+ - A cryptographic identity stamp (Ed25519)
29
+ - A public registry listing
30
+ - Heartbeat-based uptime reputation
31
+ - Auto-renewal before expiry
32
+
33
+ ## Verify Other Agents
34
+
35
+ ```python
36
+ trust = lifecycle.check_trust("0xOtherAgentWallet")
37
+ if trust.get("trusted"):
38
+ print(f"Verified: {trust['agent']['name']} (score: {trust['reputation']['score']})")
39
+ else:
40
+ print("Unverified agent — proceed with caution")
41
+ ```
42
+
43
+ ## Gate Functions Behind Verification
44
+
45
+ ```python
46
+ from agentstamp_crewai import stamp_verified
47
+
48
+ @stamp_verified(lifecycle)
49
+ def sensitive_operation(data: str) -> str:
50
+ """Only runs if the agent is AgentStamp verified."""
51
+ return process(data)
52
+ ```
53
+
54
+ ## CrewAI Integration
55
+
56
+ ```python
57
+ from crewai import Agent, Task, Crew
58
+ from agentstamp_crewai import AgentStampLifecycle
59
+
60
+ # Start lifecycle
61
+ lifecycle = AgentStampLifecycle(
62
+ wallet_address="0x...",
63
+ name="ResearchBot",
64
+ description="Finds and summarizes papers",
65
+ category="research",
66
+ )
67
+ lifecycle.start()
68
+
69
+ # Create CrewAI agent as normal
70
+ agent = Agent(
71
+ role="Researcher",
72
+ goal="Find relevant papers",
73
+ backstory="Expert research assistant",
74
+ )
75
+
76
+ # Check trust before collaborating with other agents
77
+ trust = lifecycle.check_trust("0xCollaboratorWallet")
78
+ ```
79
+
80
+ ## Configuration
81
+
82
+ | Parameter | Default | Description |
83
+ |-----------|---------|-------------|
84
+ | `wallet_address` | required | Your agent's wallet address (EVM or Solana) |
85
+ | `name` | required | Agent display name |
86
+ | `description` | required | What your agent does |
87
+ | `category` | `"other"` | `research`, `trading`, `social`, `infrastructure`, etc. |
88
+ | `heartbeat_interval` | `300` | Seconds between heartbeats |
89
+ | `renew_before_days` | `2` | Days before expiry to auto-renew |
90
+ | `verbose` | `True` | Print lifecycle logs |
91
+
92
+ ## Badge
93
+
94
+ Add a trust badge to your README:
95
+
96
+ ```markdown
97
+ ![AgentStamp](https://agentstamp.org/api/v1/badge/0xYourWallet)
98
+ ```
99
+
100
+ ## Links
101
+
102
+ - [AgentStamp](https://agentstamp.org) — Platform
103
+ - [npm SDK](https://www.npmjs.com/package/agentstamp-verify) — TypeScript/Node.js SDK
104
+ - [API Docs](https://agentstamp.org/api/v1/trust/check/0x...) — Trust check endpoint
@@ -0,0 +1,135 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentstamp
3
+ Version: 1.1.0
4
+ Summary: Identity lifecycle SDK for Python AI agents — trust stamps, registry, heartbeats, auto-renewal
5
+ Home-page: https://agentstamp.org
6
+ Author: Vinay Bhosle
7
+ Author-email: Vinay Bhosle <vinay@agentstamp.org>
8
+ License: MIT
9
+ Project-URL: Homepage, https://agentstamp.org
10
+ Project-URL: Repository, https://github.com/AgentstampHQ/agentstamp-python
11
+ Project-URL: Documentation, https://agentstamp.org
12
+ Project-URL: npm SDK, https://www.npmjs.com/package/agentstamp-verify
13
+ Keywords: agentstamp,ai-agents,crewai,autogen,langgraph,identity,trust,verification,x402,reputation
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Software Development :: Libraries
24
+ Classifier: Topic :: Security
25
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/markdown
27
+ Requires-Dist: requests>=2.20.0
28
+ Dynamic: author
29
+ Dynamic: home-page
30
+ Dynamic: requires-python
31
+
32
+ # agentstamp
33
+
34
+ Identity lifecycle SDK for Python AI agents. Works with CrewAI, AutoGen, LangGraph, and any Python agent framework.
35
+
36
+ Register your agent, mint trust stamps, send heartbeats, and auto-renew — in 3 lines.
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ pip install agentstamp
42
+ ```
43
+
44
+ ## Quick Start
45
+
46
+ ```python
47
+ from agentstamp_crewai import AgentStampLifecycle
48
+
49
+ lifecycle = AgentStampLifecycle(
50
+ wallet_address="0xYourWalletAddress",
51
+ name="MyAgent",
52
+ description="What your agent does",
53
+ category="research",
54
+ )
55
+ lifecycle.start() # stamps + registers + heartbeats + auto-renew
56
+ ```
57
+
58
+ That's it. Your agent now has:
59
+ - A cryptographic identity stamp (Ed25519)
60
+ - A public registry listing
61
+ - Heartbeat-based uptime reputation
62
+ - Auto-renewal before expiry
63
+
64
+ ## Verify Other Agents
65
+
66
+ ```python
67
+ trust = lifecycle.check_trust("0xOtherAgentWallet")
68
+ if trust.get("trusted"):
69
+ print(f"Verified: {trust['agent']['name']} (score: {trust['reputation']['score']})")
70
+ else:
71
+ print("Unverified agent — proceed with caution")
72
+ ```
73
+
74
+ ## Gate Functions Behind Verification
75
+
76
+ ```python
77
+ from agentstamp_crewai import stamp_verified
78
+
79
+ @stamp_verified(lifecycle)
80
+ def sensitive_operation(data: str) -> str:
81
+ """Only runs if the agent is AgentStamp verified."""
82
+ return process(data)
83
+ ```
84
+
85
+ ## CrewAI Integration
86
+
87
+ ```python
88
+ from crewai import Agent, Task, Crew
89
+ from agentstamp_crewai import AgentStampLifecycle
90
+
91
+ # Start lifecycle
92
+ lifecycle = AgentStampLifecycle(
93
+ wallet_address="0x...",
94
+ name="ResearchBot",
95
+ description="Finds and summarizes papers",
96
+ category="research",
97
+ )
98
+ lifecycle.start()
99
+
100
+ # Create CrewAI agent as normal
101
+ agent = Agent(
102
+ role="Researcher",
103
+ goal="Find relevant papers",
104
+ backstory="Expert research assistant",
105
+ )
106
+
107
+ # Check trust before collaborating with other agents
108
+ trust = lifecycle.check_trust("0xCollaboratorWallet")
109
+ ```
110
+
111
+ ## Configuration
112
+
113
+ | Parameter | Default | Description |
114
+ |-----------|---------|-------------|
115
+ | `wallet_address` | required | Your agent's wallet address (EVM or Solana) |
116
+ | `name` | required | Agent display name |
117
+ | `description` | required | What your agent does |
118
+ | `category` | `"other"` | `research`, `trading`, `social`, `infrastructure`, etc. |
119
+ | `heartbeat_interval` | `300` | Seconds between heartbeats |
120
+ | `renew_before_days` | `2` | Days before expiry to auto-renew |
121
+ | `verbose` | `True` | Print lifecycle logs |
122
+
123
+ ## Badge
124
+
125
+ Add a trust badge to your README:
126
+
127
+ ```markdown
128
+ ![AgentStamp](https://agentstamp.org/api/v1/badge/0xYourWallet)
129
+ ```
130
+
131
+ ## Links
132
+
133
+ - [AgentStamp](https://agentstamp.org) — Platform
134
+ - [npm SDK](https://www.npmjs.com/package/agentstamp-verify) — TypeScript/Node.js SDK
135
+ - [API Docs](https://agentstamp.org/api/v1/trust/check/0x...) — Trust check endpoint
@@ -0,0 +1,9 @@
1
+ README.md
2
+ agentstamp_crewai.py
3
+ pyproject.toml
4
+ setup.py
5
+ agentstamp.egg-info/PKG-INFO
6
+ agentstamp.egg-info/SOURCES.txt
7
+ agentstamp.egg-info/dependency_links.txt
8
+ agentstamp.egg-info/requires.txt
9
+ agentstamp.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ requests>=2.20.0
@@ -0,0 +1 @@
1
+ agentstamp_crewai
@@ -0,0 +1,374 @@
1
+ """
2
+ AgentStamp + CrewAI Integration
3
+
4
+ Drop-in identity lifecycle for CrewAI agents.
5
+ Auto-registers your agent on first run, sends heartbeats, and auto-renews.
6
+
7
+ Install:
8
+ pip install requests
9
+
10
+ Usage:
11
+ from agentstamp_crewai import AgentStampLifecycle, stamp_verified_tool
12
+
13
+ # Auto-register on startup
14
+ lifecycle = AgentStampLifecycle(
15
+ wallet_address="0x...",
16
+ name="MyResearchAgent",
17
+ description="Finds and summarizes research papers",
18
+ category="research",
19
+ )
20
+ lifecycle.start() # stamps + registers + heartbeats + auto-renew
21
+
22
+ # Use as a CrewAI tool
23
+ @stamp_verified_tool
24
+ def my_api_call(query: str) -> str:
25
+ '''Makes an API call only if the caller is AgentStamp verified.'''
26
+ return do_the_thing(query)
27
+
28
+ # Or check trust manually
29
+ trust = lifecycle.check_trust("0x_other_agent_wallet")
30
+ if trust["trusted"]:
31
+ proceed()
32
+ """
33
+
34
+ import json
35
+ import time
36
+ import threading
37
+ from typing import Optional, Callable, Any
38
+ import requests
39
+
40
+
41
+ AGENTSTAMP_API = "https://agentstamp.org"
42
+
43
+
44
+ class AgentStampLifecycle:
45
+ """
46
+ Manages the full AgentStamp identity lifecycle for a CrewAI agent.
47
+
48
+ - Auto-registers (free stamp + free directory listing) on first run
49
+ - Sends periodic heartbeats for uptime reputation
50
+ - Auto-renews stamps and registrations before they expire
51
+ """
52
+
53
+ def __init__(
54
+ self,
55
+ wallet_address: str,
56
+ name: str,
57
+ description: str,
58
+ category: str = "other",
59
+ capabilities: Optional[list] = None,
60
+ endpoint_url: Optional[str] = None,
61
+ base_url: str = AGENTSTAMP_API,
62
+ heartbeat_interval: int = 300, # seconds
63
+ renew_before_days: int = 2,
64
+ renew_check_interval: int = 3600, # seconds
65
+ verbose: bool = True,
66
+ on_registered: Optional[Callable] = None,
67
+ on_renewed: Optional[Callable] = None,
68
+ on_error: Optional[Callable] = None,
69
+ ):
70
+ self.wallet_address = wallet_address
71
+ self.name = name
72
+ self.description = description
73
+ self.category = category
74
+ self.capabilities = capabilities or []
75
+ self.endpoint_url = endpoint_url
76
+ self.base_url = base_url.rstrip("/")
77
+ self.heartbeat_interval = heartbeat_interval
78
+ self.renew_before_days = renew_before_days
79
+ self.renew_check_interval = renew_check_interval
80
+ self.verbose = verbose
81
+ self.on_registered = on_registered
82
+ self.on_renewed = on_renewed
83
+ self.on_error = on_error
84
+
85
+ # State
86
+ self.agent_id: Optional[str] = None
87
+ self.stamp_id: Optional[str] = None
88
+ self.stamp_expires_at: Optional[str] = None
89
+ self.registration_expires_at: Optional[str] = None
90
+ self.heartbeat_count: int = 0
91
+ self.initialized: bool = False
92
+
93
+ # Timers
94
+ self._heartbeat_timer: Optional[threading.Timer] = None
95
+ self._renew_timer: Optional[threading.Timer] = None
96
+ self._shutdown = False
97
+
98
+ def start(self) -> dict:
99
+ """Initialize + heartbeat + auto-renew in one call."""
100
+ state = self.initialize()
101
+ self.enable_heartbeat()
102
+ self.enable_auto_renew()
103
+ return state
104
+
105
+ def initialize(self) -> dict:
106
+ """Mint a free stamp and register if not already done."""
107
+ self._log("Initializing agent lifecycle...")
108
+
109
+ # Check if already registered
110
+ if self._check_existing():
111
+ self._log(f"Agent already registered: {self.agent_id}")
112
+ self.initialized = True
113
+ return self.get_state()
114
+
115
+ # Step 1: Mint free stamp
116
+ try:
117
+ self._log("Minting free stamp...")
118
+ resp = requests.post(
119
+ f"{self.base_url}/api/v1/stamp/mint/free",
120
+ json={"wallet_address": self.wallet_address},
121
+ headers={
122
+ "x-wallet-address": self.wallet_address,
123
+ "User-Agent": "agentstamp-crewai/1.0.0",
124
+ },
125
+ timeout=10,
126
+ )
127
+ data = resp.json()
128
+ if data.get("success") and data.get("stamp"):
129
+ self.stamp_id = data["stamp"]["id"]
130
+ self.stamp_expires_at = data["stamp"]["expires_at"]
131
+ self._log(f"Stamp minted: {self.stamp_id}")
132
+ elif "cooldown" in str(data.get("error", "")):
133
+ self._log("Free stamp cooldown active — already stamped")
134
+ except Exception as e:
135
+ self._handle_error(e, "mint_stamp")
136
+
137
+ # Step 2: Register in directory
138
+ try:
139
+ self._log("Registering agent in directory...")
140
+ resp = requests.post(
141
+ f"{self.base_url}/api/v1/registry/register/free",
142
+ json={
143
+ "wallet_address": self.wallet_address,
144
+ "name": self.name,
145
+ "description": self.description,
146
+ "category": self.category,
147
+ "capabilities": self.capabilities,
148
+ "endpoint_url": self.endpoint_url,
149
+ },
150
+ headers={
151
+ "x-wallet-address": self.wallet_address,
152
+ "User-Agent": "agentstamp-crewai/1.0.0",
153
+ },
154
+ timeout=10,
155
+ )
156
+ data = resp.json()
157
+ if data.get("success") and data.get("agent"):
158
+ self.agent_id = data["agent"]["id"]
159
+ self.registration_expires_at = data["agent"]["expires_at"]
160
+ self._log(f"Agent registered: {self.agent_id}")
161
+ if self.on_registered:
162
+ self.on_registered({"agent_id": self.agent_id, "stamp_id": self.stamp_id})
163
+ elif "cooldown" in str(data.get("error", "")):
164
+ self._log("Free registration cooldown active — already registered")
165
+ self._check_existing()
166
+ except Exception as e:
167
+ self._handle_error(e, "register")
168
+
169
+ self.initialized = True
170
+ return self.get_state()
171
+
172
+ def enable_heartbeat(self, interval: Optional[int] = None) -> None:
173
+ """Send periodic heartbeats to maintain uptime score."""
174
+ if self._heartbeat_timer is not None:
175
+ return
176
+ interval = interval or self.heartbeat_interval
177
+ self._log(f"Heartbeat enabled (every {interval}s)")
178
+ self._send_heartbeat()
179
+ self._schedule_heartbeat(interval)
180
+
181
+ def enable_auto_renew(self, check_interval: Optional[int] = None) -> None:
182
+ """Periodically check and renew stamps/registrations before expiry."""
183
+ if self._renew_timer is not None:
184
+ return
185
+ interval = check_interval or self.renew_check_interval
186
+ self._log(f"Auto-renewal enabled (check every {interval}s)")
187
+ self._check_and_renew()
188
+ self._schedule_renew(interval)
189
+
190
+ def check_trust(self, wallet_address: str) -> dict:
191
+ """Check the trust status of another agent."""
192
+ try:
193
+ resp = requests.get(
194
+ f"{self.base_url}/api/v1/trust/check/{wallet_address}",
195
+ headers={"User-Agent": "agentstamp-crewai/1.0.0"},
196
+ timeout=5,
197
+ )
198
+ return resp.json()
199
+ except Exception as e:
200
+ return {"trusted": False, "error": str(e)}
201
+
202
+ def shutdown(self) -> None:
203
+ """Stop all background timers."""
204
+ self._shutdown = True
205
+ if self._heartbeat_timer:
206
+ self._heartbeat_timer.cancel()
207
+ self._heartbeat_timer = None
208
+ if self._renew_timer:
209
+ self._renew_timer.cancel()
210
+ self._renew_timer = None
211
+ self._log("Lifecycle shut down")
212
+
213
+ def get_state(self) -> dict:
214
+ return {
215
+ "initialized": self.initialized,
216
+ "agent_id": self.agent_id,
217
+ "stamp_id": self.stamp_id,
218
+ "stamp_expires_at": self.stamp_expires_at,
219
+ "registration_expires_at": self.registration_expires_at,
220
+ "heartbeat_count": self.heartbeat_count,
221
+ }
222
+
223
+ # --- Private ---
224
+
225
+ def _check_existing(self) -> bool:
226
+ try:
227
+ resp = requests.get(
228
+ f"{self.base_url}/api/v1/trust/check/{self.wallet_address}",
229
+ headers={"User-Agent": "agentstamp-crewai/1.0.0"},
230
+ timeout=5,
231
+ )
232
+ data = resp.json()
233
+ if data.get("agent"):
234
+ self.agent_id = data["agent"].get("id")
235
+ if data.get("stamp"):
236
+ self.stamp_id = data["stamp"].get("id")
237
+ self.stamp_expires_at = data["stamp"].get("expires_at")
238
+ return data.get("trusted", False) or data.get("agent") is not None
239
+ except Exception:
240
+ return False
241
+
242
+ def _send_heartbeat(self) -> None:
243
+ if not self.agent_id or self._shutdown:
244
+ return
245
+ try:
246
+ requests.post(
247
+ f"{self.base_url}/api/v1/registry/heartbeat/{self.agent_id}",
248
+ headers={"User-Agent": "agentstamp-crewai/1.0.0"},
249
+ timeout=5,
250
+ )
251
+ self.heartbeat_count += 1
252
+ self._log(f"Heartbeat #{self.heartbeat_count} sent")
253
+ except Exception as e:
254
+ self._handle_error(e, "heartbeat")
255
+
256
+ def _schedule_heartbeat(self, interval: int) -> None:
257
+ if self._shutdown:
258
+ return
259
+ self._heartbeat_timer = threading.Timer(interval, self._heartbeat_tick, [interval])
260
+ self._heartbeat_timer.daemon = True
261
+ self._heartbeat_timer.start()
262
+
263
+ def _heartbeat_tick(self, interval: int) -> None:
264
+ if self._shutdown:
265
+ return
266
+ self._send_heartbeat()
267
+ self._schedule_heartbeat(interval)
268
+
269
+ def _check_and_renew(self) -> None:
270
+ if self._shutdown:
271
+ return
272
+ now = time.time()
273
+ threshold = self.renew_before_days * 86400
274
+
275
+ # Check stamp
276
+ if self.stamp_expires_at:
277
+ try:
278
+ from datetime import datetime
279
+ expiry = datetime.fromisoformat(self.stamp_expires_at.replace("Z", "+00:00")).timestamp()
280
+ if expiry - now < threshold:
281
+ self._log("Stamp expiring soon — renewing...")
282
+ resp = requests.post(
283
+ f"{self.base_url}/api/v1/stamp/mint/free",
284
+ json={"wallet_address": self.wallet_address},
285
+ headers={"x-wallet-address": self.wallet_address, "User-Agent": "agentstamp-crewai/1.0.0"},
286
+ timeout=10,
287
+ )
288
+ data = resp.json()
289
+ if data.get("success") and data.get("stamp"):
290
+ self.stamp_id = data["stamp"]["id"]
291
+ self.stamp_expires_at = data["stamp"]["expires_at"]
292
+ self._log(f"Stamp renewed: {self.stamp_id}")
293
+ if self.on_renewed:
294
+ self.on_renewed({"type": "stamp", "expires_at": self.stamp_expires_at})
295
+ except Exception as e:
296
+ self._handle_error(e, "renew_stamp")
297
+
298
+ # Check registration
299
+ if self.registration_expires_at:
300
+ try:
301
+ from datetime import datetime
302
+ expiry = datetime.fromisoformat(self.registration_expires_at.replace("Z", "+00:00")).timestamp()
303
+ if expiry - now < threshold:
304
+ self._log("Registration expiring soon — renewing...")
305
+ resp = requests.post(
306
+ f"{self.base_url}/api/v1/registry/register/free",
307
+ json={
308
+ "wallet_address": self.wallet_address,
309
+ "name": self.name,
310
+ "description": self.description,
311
+ "category": self.category,
312
+ "capabilities": self.capabilities,
313
+ },
314
+ headers={"x-wallet-address": self.wallet_address, "User-Agent": "agentstamp-crewai/1.0.0"},
315
+ timeout=10,
316
+ )
317
+ data = resp.json()
318
+ if data.get("success") and data.get("agent"):
319
+ self.agent_id = data["agent"]["id"]
320
+ self.registration_expires_at = data["agent"]["expires_at"]
321
+ self._log(f"Registration renewed: {self.agent_id}")
322
+ if self.on_renewed:
323
+ self.on_renewed({"type": "registration", "expires_at": self.registration_expires_at})
324
+ except Exception as e:
325
+ self._handle_error(e, "renew_registration")
326
+
327
+ def _schedule_renew(self, interval: int) -> None:
328
+ if self._shutdown:
329
+ return
330
+ self._renew_timer = threading.Timer(interval, self._renew_tick, [interval])
331
+ self._renew_timer.daemon = True
332
+ self._renew_timer.start()
333
+
334
+ def _renew_tick(self, interval: int) -> None:
335
+ if self._shutdown:
336
+ return
337
+ self._check_and_renew()
338
+ self._schedule_renew(interval)
339
+
340
+ def _handle_error(self, err: Exception, context: str) -> None:
341
+ self._log(f"Error [{context}]: {err}", is_error=True)
342
+ if self.on_error:
343
+ self.on_error(err, context)
344
+
345
+ def _log(self, message: str, is_error: bool = False) -> None:
346
+ if self.verbose:
347
+ prefix = f"[AgentStamp:{self.name}]"
348
+ if is_error:
349
+ print(f"\033[91m{prefix} {message}\033[0m")
350
+ else:
351
+ print(f"\033[96m{prefix} {message}\033[0m")
352
+
353
+
354
+ def stamp_verified(lifecycle: AgentStampLifecycle):
355
+ """
356
+ Decorator: only execute a function if the agent is AgentStamp verified.
357
+
358
+ Usage:
359
+ lifecycle = AgentStampLifecycle(...)
360
+ lifecycle.start()
361
+
362
+ @stamp_verified(lifecycle)
363
+ def my_tool(query: str) -> str:
364
+ return "result"
365
+ """
366
+ def decorator(func: Callable) -> Callable:
367
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
368
+ if not lifecycle.initialized or not lifecycle.agent_id:
369
+ return "Error: Agent not registered with AgentStamp. Call lifecycle.start() first."
370
+ return func(*args, **kwargs)
371
+ wrapper.__name__ = func.__name__
372
+ wrapper.__doc__ = func.__doc__
373
+ return wrapper
374
+ return decorator
@@ -0,0 +1,38 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "agentstamp"
7
+ version = "1.1.0"
8
+ description = "Identity lifecycle SDK for Python AI agents — trust stamps, registry, heartbeats, auto-renewal"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.8"
12
+ authors = [
13
+ {name = "Vinay Bhosle", email = "vinay@agentstamp.org"}
14
+ ]
15
+ keywords = [
16
+ "agentstamp", "ai-agents", "crewai", "autogen", "langgraph",
17
+ "identity", "trust", "verification", "x402", "reputation"
18
+ ]
19
+ classifiers = [
20
+ "Development Status :: 4 - Beta",
21
+ "Intended Audience :: Developers",
22
+ "License :: OSI Approved :: MIT License",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.8",
25
+ "Programming Language :: Python :: 3.9",
26
+ "Programming Language :: Python :: 3.10",
27
+ "Programming Language :: Python :: 3.11",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Topic :: Software Development :: Libraries",
30
+ "Topic :: Security",
31
+ ]
32
+ dependencies = ["requests>=2.20.0"]
33
+
34
+ [project.urls]
35
+ Homepage = "https://agentstamp.org"
36
+ Repository = "https://github.com/AgentstampHQ/agentstamp-python"
37
+ Documentation = "https://agentstamp.org"
38
+ "npm SDK" = "https://www.npmjs.com/package/agentstamp-verify"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,23 @@
1
+ from setuptools import setup
2
+
3
+ setup(
4
+ name="agentstamp",
5
+ version="1.1.0",
6
+ description="AgentStamp identity lifecycle for Python AI agents (CrewAI, AutoGen, etc.)",
7
+ long_description=open("README.md").read() if __import__("os").path.exists("README.md") else "",
8
+ long_description_content_type="text/markdown",
9
+ author="Vinay Bhosle",
10
+ author_email="vinay@agentstamp.org",
11
+ url="https://agentstamp.org",
12
+ py_modules=["agentstamp_crewai"],
13
+ install_requires=["requests>=2.20.0"],
14
+ python_requires=">=3.8",
15
+ license="MIT",
16
+ keywords=["agentstamp", "ai-agents", "crewai", "identity", "trust", "verification"],
17
+ classifiers=[
18
+ "Development Status :: 4 - Beta",
19
+ "Intended Audience :: Developers",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Programming Language :: Python :: 3",
22
+ ],
23
+ )