agent0-sdk 0.31__tar.gz → 1.0.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.
Files changed (39) hide show
  1. agent0_sdk-1.0.0/MANIFEST.in +10 -0
  2. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/PKG-INFO +21 -7
  3. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/README.md +19 -5
  4. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk/__init__.py +1 -1
  5. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk/core/agent.py +172 -30
  6. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk/core/contracts.py +93 -58
  7. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk/core/feedback_manager.py +90 -161
  8. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk/core/indexer.py +54 -26
  9. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk/core/models.py +6 -19
  10. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk/core/oasf_validator.py +1 -1
  11. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk/core/sdk.py +31 -16
  12. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk/core/subgraph_client.py +34 -15
  13. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk/core/web3_client.py +184 -17
  14. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk.egg-info/PKG-INFO +21 -7
  15. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk.egg-info/SOURCES.txt +2 -15
  16. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/pyproject.toml +2 -2
  17. agent0_sdk-0.31/tests/__init__.py +0 -1
  18. agent0_sdk-0.31/tests/config.py +0 -46
  19. agent0_sdk-0.31/tests/conftest.py +0 -22
  20. agent0_sdk-0.31/tests/discover_test_data.py +0 -445
  21. agent0_sdk-0.31/tests/test_feedback.py +0 -417
  22. agent0_sdk-0.31/tests/test_models.py +0 -224
  23. agent0_sdk-0.31/tests/test_multi_chain.py +0 -588
  24. agent0_sdk-0.31/tests/test_oasf_management.py +0 -404
  25. agent0_sdk-0.31/tests/test_real_public_servers.py +0 -103
  26. agent0_sdk-0.31/tests/test_registration.py +0 -267
  27. agent0_sdk-0.31/tests/test_registrationIpfs.py +0 -227
  28. agent0_sdk-0.31/tests/test_sdk.py +0 -240
  29. agent0_sdk-0.31/tests/test_search.py +0 -415
  30. agent0_sdk-0.31/tests/test_transfer.py +0 -255
  31. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/LICENSE +0 -0
  32. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk/core/endpoint_crawler.py +0 -0
  33. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk/core/ipfs_client.py +0 -0
  34. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk/taxonomies/all_domains.json +0 -0
  35. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk/taxonomies/all_skills.json +0 -0
  36. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk.egg-info/dependency_links.txt +0 -0
  37. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk.egg-info/requires.txt +0 -0
  38. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/agent0_sdk.egg-info/top_level.txt +0 -0
  39. {agent0_sdk-0.31 → agent0_sdk-1.0.0}/setup.cfg +0 -0
@@ -0,0 +1,10 @@
1
+ exclude .env
2
+ global-exclude *.env
3
+ global-exclude *.env.*
4
+
5
+ # local artifacts
6
+ prune venv
7
+ exclude agent_registration_*.json
8
+
9
+ # don't ship tests in sdist by default
10
+ prune tests
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent0-sdk
3
- Version: 0.31
3
+ Version: 1.0.0
4
4
  Summary: Python SDK for agent portability, discovery and trust based on ERC-8004
5
- Author-email: Marco De Rossi <marco.derossi@consensys.net>
5
+ Author-email: Marco De Rossi <marco@ag0.xyz>
6
6
  License: MIT License
7
7
 
8
8
  Copyright (c) 2025 Marco De Rossi
@@ -152,12 +152,15 @@ agent.setENS("myagent.eth")
152
152
 
153
153
  # Add OASF skills and domains (standardized taxonomies)
154
154
  agent.addSkill("data_engineering/data_transformation_pipeline", validate_oasf=True)
155
- agent.addSkill("natural_language_processing/summarization", validate_oasf=True)
155
+ agent.addSkill("natural_language_processing/natural_language_generation/summarization", validate_oasf=True)
156
156
  agent.addDomain("finance_and_business/investment_services", validate_oasf=True)
157
- agent.addDomain("technology/data_science", validate_oasf=True)
157
+ agent.addDomain("technology/data_science/data_science", validate_oasf=True)
158
158
 
159
159
  # Configure wallet and trust
160
- agent.setAgentWallet("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", chainId=11155111)
160
+ # Note: agentWallet is an on-chain verified attribute. setAgentWallet() is on-chain only.
161
+ # EOAs: the NEW wallet must sign an EIP-712 message. If you pass new_wallet_signer, the SDK will
162
+ # build + sign the typed data automatically.
163
+ # If the current SDK signer address matches the new wallet, it can auto-sign without new_wallet_signer.
161
164
  agent.setTrust(reputation=True, cryptoEconomic=True)
162
165
 
163
166
  # Add metadata and set status
@@ -168,6 +171,16 @@ agent.setActive(True)
168
171
  agent.registerIPFS()
169
172
  print(f"Agent registered: {agent.agentId}") # e.g., "11155111:123"
170
173
  print(f"Agent URI: {agent.agentURI}") # e.g., "ipfs://Qm..."
174
+
175
+ # (Optional) Change the agent wallet after registration
176
+ # - On mint/registration, `agentWallet` defaults to the current owner address.
177
+ # - Call this only if you want a DIFFERENT wallet (or after a transfer, since the wallet resets to zero).
178
+ # - Transaction is sent by the SDK signer (agent owner), but the signature must be produced by the NEW wallet.
179
+ agent.setAgentWallet(
180
+ "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
181
+ chainId=11155111,
182
+ new_wallet_signer=os.getenv("NEW_WALLET_PRIVATE_KEY"),
183
+ )
171
184
  ```
172
185
 
173
186
  ### 3. Load and Edit Agent
@@ -213,7 +226,8 @@ agent_summary = sdk.getAgent("11155111:123")
213
226
  feedback_file = sdk.prepareFeedback(
214
227
  agentId="11155111:123",
215
228
  score=85, # 0-100 (mandatory)
216
- tags=["data_analyst", "finance"], # Optional
229
+ tags=["data_analyst", "finance"], # Optional: tags are now strings (not bytes32)
230
+ endpoint="https://example.com/endpoint", # Optional: endpoint URI associated with feedback
217
231
  capability="tools", # Optional: MCP capability
218
232
  name="code_generation", # Optional: MCP tool name
219
233
  skill="python" # Optional: A2A skill
@@ -307,7 +321,7 @@ OASF skills and domains appear in your agent's registration file:
307
321
  ],
308
322
  "domains": [
309
323
  "finance_and_business/investment_services",
310
- "technology/data_science"
324
+ "technology/data_science/data_science"
311
325
  ]
312
326
  }
313
327
  ]
@@ -82,12 +82,15 @@ agent.setENS("myagent.eth")
82
82
 
83
83
  # Add OASF skills and domains (standardized taxonomies)
84
84
  agent.addSkill("data_engineering/data_transformation_pipeline", validate_oasf=True)
85
- agent.addSkill("natural_language_processing/summarization", validate_oasf=True)
85
+ agent.addSkill("natural_language_processing/natural_language_generation/summarization", validate_oasf=True)
86
86
  agent.addDomain("finance_and_business/investment_services", validate_oasf=True)
87
- agent.addDomain("technology/data_science", validate_oasf=True)
87
+ agent.addDomain("technology/data_science/data_science", validate_oasf=True)
88
88
 
89
89
  # Configure wallet and trust
90
- agent.setAgentWallet("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", chainId=11155111)
90
+ # Note: agentWallet is an on-chain verified attribute. setAgentWallet() is on-chain only.
91
+ # EOAs: the NEW wallet must sign an EIP-712 message. If you pass new_wallet_signer, the SDK will
92
+ # build + sign the typed data automatically.
93
+ # If the current SDK signer address matches the new wallet, it can auto-sign without new_wallet_signer.
91
94
  agent.setTrust(reputation=True, cryptoEconomic=True)
92
95
 
93
96
  # Add metadata and set status
@@ -98,6 +101,16 @@ agent.setActive(True)
98
101
  agent.registerIPFS()
99
102
  print(f"Agent registered: {agent.agentId}") # e.g., "11155111:123"
100
103
  print(f"Agent URI: {agent.agentURI}") # e.g., "ipfs://Qm..."
104
+
105
+ # (Optional) Change the agent wallet after registration
106
+ # - On mint/registration, `agentWallet` defaults to the current owner address.
107
+ # - Call this only if you want a DIFFERENT wallet (or after a transfer, since the wallet resets to zero).
108
+ # - Transaction is sent by the SDK signer (agent owner), but the signature must be produced by the NEW wallet.
109
+ agent.setAgentWallet(
110
+ "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
111
+ chainId=11155111,
112
+ new_wallet_signer=os.getenv("NEW_WALLET_PRIVATE_KEY"),
113
+ )
101
114
  ```
102
115
 
103
116
  ### 3. Load and Edit Agent
@@ -143,7 +156,8 @@ agent_summary = sdk.getAgent("11155111:123")
143
156
  feedback_file = sdk.prepareFeedback(
144
157
  agentId="11155111:123",
145
158
  score=85, # 0-100 (mandatory)
146
- tags=["data_analyst", "finance"], # Optional
159
+ tags=["data_analyst", "finance"], # Optional: tags are now strings (not bytes32)
160
+ endpoint="https://example.com/endpoint", # Optional: endpoint URI associated with feedback
147
161
  capability="tools", # Optional: MCP capability
148
162
  name="code_generation", # Optional: MCP tool name
149
163
  skill="python" # Optional: A2A skill
@@ -237,7 +251,7 @@ OASF skills and domains appear in your agent's registration file:
237
251
  ],
238
252
  "domains": [
239
253
  "finance_and_business/investment_services",
240
- "technology/data_science"
254
+ "technology/data_science/data_science"
241
255
  ]
242
256
  }
243
257
  ]
@@ -30,7 +30,7 @@ except ImportError:
30
30
  Agent = None
31
31
  _sdk_available = False
32
32
 
33
- __version__ = "0.31"
33
+ __version__ = "1.0.0"
34
34
  __all__ = [
35
35
  "SDK",
36
36
  "Agent",
@@ -176,16 +176,14 @@ class Agent:
176
176
  return self.registration_file
177
177
 
178
178
  def _collectMetadataForRegistration(self) -> List[Dict[str, Any]]:
179
- """Collect all metadata entries for registration."""
179
+ """Collect all metadata entries for registration.
180
+
181
+ Note: agentWallet is now a reserved metadata key and cannot be set via setMetadata().
182
+ It must be set separately using setAgentWallet() with EIP-712 signature verification.
183
+ """
180
184
  metadata_entries = []
181
185
 
182
- # Add wallet address metadata
183
- if self.walletAddress:
184
- addr_bytes = bytes.fromhex(self.walletAddress[2:]) # Remove '0x' prefix
185
- metadata_entries.append({
186
- "key": "agentWallet",
187
- "value": addr_bytes
188
- })
186
+ # Note: agentWallet is no longer set via metadata - it's now reserved and managed via setAgentWallet()
189
187
 
190
188
  # Add ENS name metadata
191
189
  if self.ensEndpoint:
@@ -339,7 +337,7 @@ class Agent:
339
337
  Add a skill to the OASF endpoint.
340
338
 
341
339
  Args:
342
- slug: The skill slug to add (e.g., "natural_language_processing/summarization")
340
+ slug: The skill slug to add (e.g., "natural_language_processing/natural_language_generation/summarization")
343
341
  validate_oasf: If True, validate the slug against the OASF taxonomy (default: False)
344
342
 
345
343
  Returns:
@@ -492,20 +490,55 @@ class Agent:
492
490
  self.registration_file.updatedAt = int(time.time())
493
491
  return self
494
492
 
495
- def setAgentWallet(self, addr: Optional[Address], chainId: Optional[int] = None) -> 'Agent':
496
- """Set agent wallet address in registration file (will be saved on-chain during next register call)."""
497
- # Validate address format if provided
498
- if addr:
499
- if not addr.startswith("0x") or len(addr) != 42:
500
- raise ValueError(f"Invalid Ethereum address format: {addr}. Must be 42 characters starting with '0x'")
501
-
502
- # Validate hexadecimal characters
503
- try:
504
- int(addr[2:], 16)
505
- except ValueError:
506
- raise ValueError(f"Invalid hexadecimal characters in address: {addr}")
493
+ def setAgentWallet(
494
+ self,
495
+ new_wallet: Address,
496
+ chainId: Optional[int] = None,
497
+ *,
498
+ new_wallet_signer: Optional[Union[str, Any]] = None,
499
+ deadline: Optional[int] = None,
500
+ signature: Optional[bytes] = None,
501
+ ) -> 'Agent':
502
+ """Set agent wallet address on-chain (ERC-8004 agentWallet).
503
+
504
+ This method is **on-chain only**. The `agentWallet` is a verified attribute and must be set via
505
+ the IdentityRegistry `setAgentWallet` function.
506
+
507
+ EOAs: provide `new_wallet_signer` (private key string or eth-account account) OR ensure the SDK
508
+ signer address matches `new_wallet` so the SDK can auto-sign.\n
509
+ Contract wallets (ERC-1271): provide `signature` bytes produced by the wallet’s signing mechanism.
510
+ The SDK will build the correct EIP-712 typed data internally, but cannot produce the wallet signature.
511
+
512
+ Args:
513
+ new_wallet: New wallet address (must be controlled by the signer that produces the signature)
514
+ chainId: Optional local bookkeeping for registration file (walletChainId). Defaults to agent chain.
515
+ new_wallet_signer: EOA signer used to sign the EIP-712 message (private key string or eth-account account)
516
+ deadline: Signature deadline timestamp. Defaults to now+60s (must be <= now+5min per contract).
517
+ signature: Raw signature bytes (intended for ERC-1271 / external signing only)
518
+ """
519
+ # Breaking/clean: this API is only meaningful for already-registered agents.
520
+ if not self.agentId:
521
+ raise ValueError(
522
+ "Cannot set agent wallet before the agent is registered on-chain. "
523
+ "Call agent.register(...) / agent.registerIPFS() first to obtain agentId."
524
+ )
525
+
526
+ addr = new_wallet
527
+
528
+ if not addr:
529
+ raise ValueError("Wallet address cannot be empty. Use a non-zero address.")
507
530
 
508
- # Determine chain ID to use
531
+ # Validate address format
532
+ if not addr.startswith("0x") or len(addr) != 42:
533
+ raise ValueError(f"Invalid Ethereum address format: {addr}. Must be 42 characters starting with '0x'")
534
+
535
+ # Validate hexadecimal characters
536
+ try:
537
+ int(addr[2:], 16)
538
+ except ValueError:
539
+ raise ValueError(f"Invalid hexadecimal characters in address: {addr}")
540
+
541
+ # Determine chain ID to use (local bookkeeping)
509
542
  if chainId is None:
510
543
  # Extract chain ID from agentId if available, otherwise use SDK's chain ID
511
544
  if self.agentId and ":" in self.agentId:
@@ -516,14 +549,104 @@ class Agent:
516
549
  else:
517
550
  chainId = self.sdk.chainId # Use SDK's chain ID as fallback
518
551
 
519
- # Check if wallet changed
520
- if addr != self._last_registered_wallet:
521
- self._dirty_metadata.add("agentWallet")
552
+ # Parse agent ID
553
+ agent_id_int = int(self.agentId.split(":")[-1]) if ":" in self.agentId else int(self.agentId)
554
+
555
+ # Check if wallet is already set to this address (skip if same)
556
+ try:
557
+ current_wallet = self.sdk.web3_client.call_contract(
558
+ self.sdk.identity_registry,
559
+ "getAgentWallet",
560
+ agent_id_int
561
+ )
562
+ if current_wallet and current_wallet.lower() == addr.lower():
563
+ logger.debug(f"Agent wallet is already set to {addr}, skipping on-chain update")
564
+ # Still update local registration file
565
+ self.registration_file.walletAddress = addr
566
+ self.registration_file.walletChainId = chainId
567
+ self.registration_file.updatedAt = int(time.time())
568
+ return self
569
+ except Exception as e:
570
+ logger.debug(f"Could not check current agent wallet: {e}, proceeding with update")
571
+
572
+ # Set deadline (default to 60 seconds from now; contract max is now+5min)
573
+ if deadline is None:
574
+ deadline = int(time.time()) + 60
575
+
576
+ # Resolve typed data + signature
577
+ identity_registry_address = self.sdk.identity_registry.address
578
+ owner_address = self.sdk.web3_client.call_contract(self.sdk.identity_registry, "ownerOf", agent_id_int)
579
+
580
+ full_message = self.sdk.web3_client.build_agent_wallet_set_typed_data(
581
+ agent_id=agent_id_int,
582
+ new_wallet=addr,
583
+ owner=owner_address,
584
+ deadline=deadline,
585
+ verifying_contract=identity_registry_address,
586
+ chain_id=self.sdk.web3_client.chain_id,
587
+ )
588
+
589
+ if signature is None:
590
+ # EOA signing paths
591
+ if new_wallet_signer is not None:
592
+ # Validate signer address matches addr (fail fast)
593
+ try:
594
+ from eth_account import Account as _Account
595
+ if isinstance(new_wallet_signer, str):
596
+ signer_addr = _Account.from_key(new_wallet_signer).address
597
+ else:
598
+ signer_addr = getattr(new_wallet_signer, "address", None)
599
+ except Exception:
600
+ signer_addr = getattr(new_wallet_signer, "address", None)
601
+
602
+ if not signer_addr or signer_addr.lower() != addr.lower():
603
+ raise ValueError(
604
+ f"new_wallet_signer address ({signer_addr}) does not match new_wallet ({addr})."
605
+ )
606
+
607
+ signature = self.sdk.web3_client.sign_typed_data(full_message, new_wallet_signer) # type: ignore[arg-type]
608
+ else:
609
+ # Auto-sign only if SDK signer == new wallet
610
+ current_address = self.sdk.web3_client.account.address if self.sdk.web3_client.account else None
611
+ if current_address and current_address.lower() == addr.lower():
612
+ signature = self.sdk.web3_client.sign_typed_data(full_message, self.sdk.web3_client.account)
613
+ else:
614
+ raise ValueError(
615
+ f"New wallet must sign. Provide new_wallet_signer (EOA) or signature (ERC-1271/external). "
616
+ f"SDK signer is {current_address}, new_wallet is {addr}."
617
+ )
618
+
619
+ # Optional: verify recover matches addr for EOA signatures
620
+ recovered = self.sdk.web3_client.w3.eth.account.recover_message(
621
+ __import__("eth_account.messages").messages.encode_typed_data(full_message=full_message),
622
+ signature=signature,
623
+ )
624
+ if recovered.lower() != addr.lower():
625
+ raise ValueError(f"Signature verification failed: recovered {recovered} but expected {addr}")
626
+
627
+ # Call setAgentWallet on the contract
628
+ try:
629
+ txHash = self.sdk.web3_client.transact_contract(
630
+ self.sdk.identity_registry,
631
+ "setAgentWallet",
632
+ agent_id_int,
633
+ addr,
634
+ deadline,
635
+ signature
636
+ )
637
+
638
+ # Wait for transaction
639
+ receipt = self.sdk.web3_client.wait_for_transaction(txHash)
640
+ logger.debug(f"Agent wallet set on-chain: {txHash}")
641
+
642
+ except Exception as e:
643
+ raise ValueError(f"Failed to set agent wallet on-chain: {e}")
522
644
 
523
645
  # Update local registration file
524
646
  self.registration_file.walletAddress = addr
525
647
  self.registration_file.walletChainId = chainId
526
648
  self.registration_file.updatedAt = int(time.time())
649
+ self._last_registered_wallet = addr
527
650
 
528
651
  return self
529
652
 
@@ -636,7 +759,7 @@ class Agent:
636
759
  agentId = int(self.agentId.split(":")[-1])
637
760
  txHash = self.sdk.web3_client.transact_contract(
638
761
  self.sdk.identity_registry,
639
- "setAgentUri",
762
+ "setAgentURI",
640
763
  agentId,
641
764
  f"ipfs://{ipfsCid}"
642
765
  )
@@ -673,7 +796,7 @@ class Agent:
673
796
  agentId = int(self.agentId.split(":")[-1])
674
797
  txHash = self.sdk.web3_client.transact_contract(
675
798
  self.sdk.identity_registry,
676
- "setAgentUri",
799
+ "setAgentURI",
677
800
  agentId,
678
801
  f"ipfs://{ipfsCid}"
679
802
  )
@@ -715,7 +838,7 @@ class Agent:
715
838
  txHash = self.sdk.web3_client.transact_contract(
716
839
  self.sdk.identity_registry,
717
840
  "register",
718
- "", # Empty tokenUri for now
841
+ "", # Empty agentURI for now
719
842
  metadata_entries
720
843
  )
721
844
 
@@ -820,7 +943,7 @@ class Agent:
820
943
  agentId = int(self.registration_file.agentId.split(":")[-1])
821
944
  txHash = self.sdk.web3_client.transact_contract(
822
945
  self.sdk.identity_registry,
823
- "setAgentUri",
946
+ "setAgentURI",
824
947
  agentId,
825
948
  agentURI
826
949
  )
@@ -846,7 +969,12 @@ class Agent:
846
969
  approve_operator: bool = False,
847
970
  idem: Optional[IdemKey] = None,
848
971
  ) -> Dict[str, Any]:
849
- """Transfer agent ownership."""
972
+ """Transfer agent ownership.
973
+
974
+ Note: When an agent is transferred, the agentWallet is automatically reset
975
+ to the zero address on-chain. The new owner must call setAgentWallet() to
976
+ set a new wallet address with EIP-712 signature verification.
977
+ """
850
978
  if not self.registration_file.agentId:
851
979
  raise ValueError("Agent must be registered before transferring")
852
980
 
@@ -863,6 +991,11 @@ class Agent:
863
991
 
864
992
  receipt = self.sdk.web3_client.wait_for_transaction(txHash)
865
993
 
994
+ # Note: agentWallet will be reset to zero address by the contract
995
+ # Update local state to reflect this
996
+ self.registration_file.walletAddress = None
997
+ self._last_registered_wallet = None
998
+
866
999
  return {
867
1000
  "txHash": txHash,
868
1001
  "agentId": self.registration_file.agentId,
@@ -907,6 +1040,10 @@ class Agent:
907
1040
 
908
1041
  Only the current owner can transfer the agent.
909
1042
 
1043
+ Note: When an agent is transferred, the agentWallet is automatically reset
1044
+ to the zero address on-chain. The new owner must call setAgentWallet() to
1045
+ set a new wallet address with EIP-712 signature verification.
1046
+
910
1047
  Args:
911
1048
  newOwnerAddress: Ethereum address of the new owner
912
1049
 
@@ -964,6 +1101,11 @@ class Agent:
964
1101
 
965
1102
  logger.debug(f"Agent {self.registration_file.agentId} successfully transferred to {checksum_address}")
966
1103
 
1104
+ # Note: agentWallet will be reset to zero address by the contract
1105
+ # Update local state to reflect this
1106
+ self.registration_file.walletAddress = None
1107
+ self._last_registered_wallet = None
1108
+
967
1109
  return {"txHash": txHash, "from": currentOwner, "to": checksum_address, "agentId": self.registration_file.agentId}
968
1110
 
969
1111
  def activate(self, idem: Optional[IdemKey] = None) -> RegistrationFile: