autogen-xache 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.
@@ -0,0 +1,297 @@
1
+ Metadata-Version: 2.4
2
+ Name: autogen-xache
3
+ Version: 0.1.0
4
+ Summary: AutoGen integration for Xache Protocol - verifiable AI agent memory
5
+ Author-email: Xache Protocol <dev@xache.xyz>
6
+ License: MIT
7
+ Project-URL: Homepage, https://xache.xyz
8
+ Project-URL: Documentation, https://docs.xache.xyz
9
+ Project-URL: Repository, https://github.com/oliveskin/xache
10
+ Keywords: autogen,ai,agents,memory,multi-agent,blockchain,receipts,reputation,erc8004,x402
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Requires-Python: >=3.9
22
+ Description-Content-Type: text/markdown
23
+ Requires-Dist: xache>=0.1.0
24
+ Requires-Dist: pyautogen>=0.2.0
25
+ Requires-Dist: pydantic>=2.0.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
28
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
29
+ Requires-Dist: black>=23.0.0; extra == "dev"
30
+ Requires-Dist: isort>=5.12.0; extra == "dev"
31
+
32
+ # autogen-xache
33
+
34
+ AutoGen integration for [Xache Protocol](https://xache.xyz) - verifiable AI agent memory with cryptographic receipts, collective intelligence, and portable ERC-8004 reputation.
35
+
36
+ ## Installation
37
+
38
+ ```bash
39
+ pip install autogen-xache
40
+ ```
41
+
42
+ ## Quick Start
43
+
44
+ ### Create an Agent with Xache Memory
45
+
46
+ ```python
47
+ from autogen import UserProxyAgent
48
+ from xache_autogen import XacheAssistantAgent
49
+
50
+ # Create an assistant with Xache capabilities
51
+ assistant = XacheAssistantAgent(
52
+ name="assistant",
53
+ wallet_address="0x...",
54
+ private_key="0x...",
55
+ llm_config={"model": "gpt-4"}
56
+ )
57
+
58
+ # Create a user proxy
59
+ user_proxy = UserProxyAgent(
60
+ name="user",
61
+ human_input_mode="TERMINATE"
62
+ )
63
+
64
+ # Start conversation
65
+ user_proxy.initiate_chat(
66
+ assistant,
67
+ message="Research quantum computing and remember the key findings"
68
+ )
69
+ ```
70
+
71
+ ### Add Xache Functions to Any Agent
72
+
73
+ ```python
74
+ from autogen import AssistantAgent
75
+ from xache_autogen import xache_functions
76
+
77
+ # Add Xache functions to LLM config
78
+ llm_config = {
79
+ "model": "gpt-4",
80
+ "functions": xache_functions
81
+ }
82
+
83
+ agent = AssistantAgent(
84
+ name="researcher",
85
+ llm_config=llm_config
86
+ )
87
+ ```
88
+
89
+ ## Features
90
+
91
+ ### Available Functions
92
+
93
+ The `xache_functions` list provides these capabilities:
94
+
95
+ #### Memory Functions
96
+ - **xache_memory_store** - Store information with cryptographic receipts
97
+ - **xache_memory_retrieve** - Retrieve stored memories by semantic search
98
+
99
+ #### Collective Intelligence Functions
100
+ - **xache_collective_contribute** - Share insights with other agents
101
+ - **xache_collective_query** - Learn from community knowledge
102
+
103
+ #### Reputation Functions
104
+ - **xache_check_reputation** - View reputation score and ERC-8004 status
105
+
106
+ ### Agent Types
107
+
108
+ #### XacheMemoryAgent
109
+
110
+ Basic conversable agent with Xache capabilities:
111
+
112
+ ```python
113
+ from xache_autogen import XacheMemoryAgent
114
+
115
+ agent = XacheMemoryAgent(
116
+ name="researcher",
117
+ wallet_address="0x...",
118
+ private_key="0x...",
119
+ llm_config={"model": "gpt-4"}
120
+ )
121
+ ```
122
+
123
+ #### XacheAssistantAgent
124
+
125
+ Extended AssistantAgent with Xache capabilities:
126
+
127
+ ```python
128
+ from xache_autogen import XacheAssistantAgent
129
+
130
+ assistant = XacheAssistantAgent(
131
+ name="assistant",
132
+ wallet_address="0x...",
133
+ private_key="0x...",
134
+ system_message="You are a helpful assistant with persistent memory.",
135
+ llm_config={"model": "gpt-4"}
136
+ )
137
+ ```
138
+
139
+ ### Conversation Memory
140
+
141
+ Store and retrieve conversation history:
142
+
143
+ ```python
144
+ from xache_autogen import XacheConversationMemory
145
+
146
+ memory = XacheConversationMemory(
147
+ wallet_address="0x...",
148
+ private_key="0x...",
149
+ conversation_id="unique-session-id"
150
+ )
151
+
152
+ # Add messages
153
+ memory.add_message("user", "Hello!")
154
+ memory.add_message("assistant", "Hi there! How can I help?")
155
+
156
+ # Get history
157
+ history = memory.get_history()
158
+
159
+ # Store a summary
160
+ memory.store_summary("User greeted the assistant.")
161
+
162
+ # Search past conversations
163
+ results = memory.search("quantum computing")
164
+
165
+ # Format for prompt
166
+ context = memory.format_for_prompt(max_messages=5)
167
+ ```
168
+
169
+ ## Multi-Agent Conversations
170
+
171
+ Xache works seamlessly with multi-agent setups:
172
+
173
+ ```python
174
+ from autogen import UserProxyAgent, GroupChat, GroupChatManager
175
+ from xache_autogen import XacheAssistantAgent
176
+
177
+ # Shared wallet = shared memory
178
+ config = {
179
+ "wallet_address": "0x...",
180
+ "private_key": "0x...",
181
+ }
182
+
183
+ researcher = XacheAssistantAgent(
184
+ name="researcher",
185
+ system_message="You research topics and store findings.",
186
+ llm_config={"model": "gpt-4"},
187
+ **config
188
+ )
189
+
190
+ writer = XacheAssistantAgent(
191
+ name="writer",
192
+ system_message="You write articles based on research.",
193
+ llm_config={"model": "gpt-4"},
194
+ **config
195
+ )
196
+
197
+ user_proxy = UserProxyAgent(name="user")
198
+
199
+ # Create group chat
200
+ groupchat = GroupChat(
201
+ agents=[user_proxy, researcher, writer],
202
+ messages=[],
203
+ max_round=10
204
+ )
205
+
206
+ manager = GroupChatManager(
207
+ groupchat=groupchat,
208
+ llm_config={"model": "gpt-4"}
209
+ )
210
+
211
+ # Both agents share the same memory pool
212
+ user_proxy.initiate_chat(
213
+ manager,
214
+ message="Research AI safety and write an article"
215
+ )
216
+ ```
217
+
218
+ ## Direct Function Usage
219
+
220
+ Use Xache functions directly outside agents:
221
+
222
+ ```python
223
+ from xache_autogen import (
224
+ memory_store,
225
+ memory_retrieve,
226
+ collective_contribute,
227
+ collective_query,
228
+ check_reputation,
229
+ )
230
+
231
+ config = {
232
+ "wallet_address": "0x...",
233
+ "private_key": "0x...",
234
+ }
235
+
236
+ # Store a memory
237
+ result = memory_store(
238
+ content="Important finding about quantum computing",
239
+ context="research",
240
+ tags=["quantum", "computing"],
241
+ **config
242
+ )
243
+ print(f"Stored: {result['memoryId']}")
244
+
245
+ # Retrieve memories
246
+ memories = memory_retrieve(
247
+ query="quantum computing",
248
+ limit=5,
249
+ **config
250
+ )
251
+ print(f"Found {memories['count']} memories")
252
+
253
+ # Contribute to collective
254
+ collective_contribute(
255
+ insight="Quantum computers excel at optimization problems",
256
+ domain="quantum-computing",
257
+ evidence="Research paper XYZ",
258
+ **config
259
+ )
260
+
261
+ # Query collective
262
+ insights = collective_query(
263
+ query="quantum computing applications",
264
+ domain="quantum-computing",
265
+ **config
266
+ )
267
+
268
+ # Check reputation
269
+ rep = check_reputation(**config)
270
+ print(f"Reputation: {rep['score']} ({rep['level']})")
271
+ ```
272
+
273
+ ## Pricing
274
+
275
+ All operations use x402 micropayments (auto-handled):
276
+
277
+ | Operation | Price |
278
+ |-----------|-------|
279
+ | Memory Store | $0.002 |
280
+ | Memory Retrieve | $0.003 |
281
+ | Collective Contribute | $0.002 |
282
+ | Collective Query | $0.011 |
283
+
284
+ ## ERC-8004 Portable Reputation
285
+
286
+ Your agents build reputation through quality contributions and payments. Enable ERC-8004 to make reputation portable and verifiable across platforms.
287
+
288
+ ## Resources
289
+
290
+ - [Documentation](https://docs.xache.xyz)
291
+ - [API Reference](https://docs.xache.xyz/api)
292
+ - [GitHub](https://github.com/oliveskin/xache)
293
+ - [Discord](https://discord.gg/xache)
294
+
295
+ ## License
296
+
297
+ MIT
@@ -0,0 +1,9 @@
1
+ xache_autogen/__init__.py,sha256=s4Lj9MXFImvo7KZiV0x6DRfAK1du3R4Zxor2EGvYiNM,1242
2
+ xache_autogen/_async_utils.py,sha256=5J3Thx1YzGHnCSVXAbxf5geuARbIJsHy__XVNPAdKj0,1635
3
+ xache_autogen/agent.py,sha256=Ns62M837HBL_fjv5vDvg9VjazgsWD0dPrqUMD3H-TpE,10223
4
+ xache_autogen/functions.py,sha256=yx-NPPPfAhR_7WoAEGYIA94j9scWX8rq9QEOQfaDnN0,11323
5
+ xache_autogen/memory.py,sha256=VS-fUbeMWil5pjQUGFLNXGUGvjtIMJQXkHkIGgNWvzk,6903
6
+ autogen_xache-0.1.0.dist-info/METADATA,sha256=zIpN_8Z9J8-t1R0TUwyVjec0mS0cItXC11YlH3_rHl8,7356
7
+ autogen_xache-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
8
+ autogen_xache-0.1.0.dist-info/top_level.txt,sha256=6Hsa4sEsdRw_49EhDw7-VWMRLgg7RYv2q02ozjF8S9Q,14
9
+ autogen_xache-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ xache_autogen
@@ -0,0 +1,51 @@
1
+ """
2
+ AutoGen integration for Xache Protocol
3
+ Verifiable memory, collective intelligence, and reputation for multi-agent conversations
4
+
5
+ Example:
6
+ ```python
7
+ from autogen import AssistantAgent, UserProxyAgent
8
+ from xache_autogen import XacheMemoryAgent, xache_functions
9
+
10
+ # Create an agent with Xache memory capabilities
11
+ assistant = XacheMemoryAgent(
12
+ name="assistant",
13
+ wallet_address="0x...",
14
+ private_key="0x...",
15
+ llm_config={"model": "gpt-4"}
16
+ )
17
+
18
+ # Or add Xache functions to any agent
19
+ agent = AssistantAgent(
20
+ name="researcher",
21
+ llm_config={"model": "gpt-4", "functions": xache_functions}
22
+ )
23
+ ```
24
+ """
25
+
26
+ from .agent import XacheMemoryAgent, XacheAssistantAgent
27
+ from .functions import (
28
+ xache_functions,
29
+ memory_store,
30
+ memory_retrieve,
31
+ collective_contribute,
32
+ collective_query,
33
+ check_reputation,
34
+ )
35
+ from .memory import XacheConversationMemory
36
+
37
+ __version__ = "0.1.0"
38
+ __all__ = [
39
+ # Agents
40
+ "XacheMemoryAgent",
41
+ "XacheAssistantAgent",
42
+ # Functions
43
+ "xache_functions",
44
+ "memory_store",
45
+ "memory_retrieve",
46
+ "collective_contribute",
47
+ "collective_query",
48
+ "check_reputation",
49
+ # Memory
50
+ "XacheConversationMemory",
51
+ ]
@@ -0,0 +1,55 @@
1
+ """
2
+ Async utilities for running coroutines in any context.
3
+ Handles Jupyter notebooks, async frameworks, and sync contexts.
4
+ """
5
+
6
+ import asyncio
7
+ from typing import TypeVar, Coroutine, Any
8
+
9
+ T = TypeVar('T')
10
+
11
+
12
+ def run_sync(coro: Coroutine[Any, Any, T]) -> T:
13
+ """
14
+ Run an async coroutine synchronously in any context.
15
+
16
+ Works correctly in:
17
+ - Regular sync Python scripts
18
+ - Jupyter notebooks (where event loop is already running)
19
+ - Async frameworks (FastAPI, etc.)
20
+
21
+ Args:
22
+ coro: The coroutine to run
23
+
24
+ Returns:
25
+ The result of the coroutine
26
+ """
27
+ try:
28
+ # Check if there's already a running event loop
29
+ loop = asyncio.get_running_loop()
30
+ except RuntimeError:
31
+ # No running loop - we can safely use asyncio.run()
32
+ return asyncio.run(coro)
33
+
34
+ # There's a running loop - we need to handle this carefully
35
+ try:
36
+ # Try using nest_asyncio for Jupyter compatibility
37
+ import nest_asyncio
38
+ nest_asyncio.apply()
39
+ return loop.run_until_complete(coro)
40
+ except ImportError:
41
+ # nest_asyncio not installed - use thread pool as fallback
42
+ import concurrent.futures
43
+
44
+ def _run_in_thread():
45
+ # Create a new event loop for this thread
46
+ new_loop = asyncio.new_event_loop()
47
+ asyncio.set_event_loop(new_loop)
48
+ try:
49
+ return new_loop.run_until_complete(coro)
50
+ finally:
51
+ new_loop.close()
52
+
53
+ with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
54
+ future = pool.submit(_run_in_thread)
55
+ return future.result()
xache_autogen/agent.py ADDED
@@ -0,0 +1,300 @@
1
+ """
2
+ Xache-enabled Agents for AutoGen
3
+ Agents with built-in Xache memory and collective intelligence capabilities
4
+ """
5
+
6
+ import os
7
+ from typing import Any, Callable, Dict, List, Optional, Union
8
+ from functools import partial
9
+
10
+ try:
11
+ from autogen import AssistantAgent, ConversableAgent
12
+ except ImportError:
13
+ raise ImportError(
14
+ "AutoGen is required. Install it with: pip install pyautogen"
15
+ )
16
+
17
+ from .functions import (
18
+ memory_store,
19
+ memory_retrieve,
20
+ collective_contribute,
21
+ collective_query,
22
+ check_reputation,
23
+ xache_functions,
24
+ )
25
+
26
+
27
+ class XacheMemoryAgent(ConversableAgent):
28
+ """
29
+ AutoGen agent with built-in Xache memory capabilities.
30
+
31
+ This agent automatically has access to Xache memory, collective intelligence,
32
+ and reputation functions.
33
+
34
+ Example:
35
+ ```python
36
+ from xache_autogen import XacheMemoryAgent
37
+
38
+ agent = XacheMemoryAgent(
39
+ name="researcher",
40
+ wallet_address="0x...",
41
+ private_key="0x...",
42
+ llm_config={"model": "gpt-4"}
43
+ )
44
+ ```
45
+ """
46
+
47
+ def __init__(
48
+ self,
49
+ name: str,
50
+ wallet_address: str,
51
+ private_key: str,
52
+ api_url: Optional[str] = None,
53
+ chain: str = "base",
54
+ system_message: Optional[str] = None,
55
+ llm_config: Optional[Dict] = None,
56
+ timeout: int = 30000,
57
+ debug: bool = False,
58
+ **kwargs
59
+ ):
60
+ # Build xache config with env-based default
61
+ resolved_api_url = api_url or os.environ.get("XACHE_API_URL", "https://api.xache.xyz")
62
+ self._xache_config = {
63
+ "wallet_address": wallet_address,
64
+ "private_key": private_key,
65
+ "api_url": resolved_api_url,
66
+ "chain": chain,
67
+ "timeout": timeout,
68
+ "debug": debug,
69
+ }
70
+
71
+ # Create bound function map
72
+ self._xache_function_map = self._create_function_map()
73
+
74
+ # Add Xache functions to llm_config (with deduplication)
75
+ if llm_config is None:
76
+ llm_config = {}
77
+
78
+ if "functions" not in llm_config:
79
+ llm_config["functions"] = []
80
+
81
+ # Deduplicate: only add xache functions that aren't already present
82
+ existing_names = {f.get("name") for f in llm_config["functions"]}
83
+ for func in xache_functions:
84
+ if func.get("name") not in existing_names:
85
+ llm_config["functions"].append(func)
86
+ existing_names.add(func.get("name"))
87
+
88
+ # Default system message
89
+ if system_message is None:
90
+ system_message = (
91
+ "You are a helpful assistant with access to persistent memory "
92
+ "and collective intelligence through Xache Protocol. "
93
+ "You can store important information, retrieve past memories, "
94
+ "contribute insights to help other agents, and query the collective "
95
+ "knowledge pool."
96
+ )
97
+
98
+ super().__init__(
99
+ name=name,
100
+ system_message=system_message,
101
+ llm_config=llm_config,
102
+ **kwargs
103
+ )
104
+
105
+ # Register function executors
106
+ self._register_xache_functions()
107
+
108
+ def _create_function_map(self) -> Dict[str, Callable]:
109
+ """Create bound functions with Xache config"""
110
+ config = self._xache_config
111
+ return {
112
+ "xache_memory_store": partial(
113
+ memory_store,
114
+ wallet_address=config["wallet_address"],
115
+ private_key=config["private_key"],
116
+ api_url=config["api_url"],
117
+ chain=config["chain"],
118
+ ),
119
+ "xache_memory_retrieve": partial(
120
+ memory_retrieve,
121
+ wallet_address=config["wallet_address"],
122
+ private_key=config["private_key"],
123
+ api_url=config["api_url"],
124
+ chain=config["chain"],
125
+ ),
126
+ "xache_collective_contribute": partial(
127
+ collective_contribute,
128
+ wallet_address=config["wallet_address"],
129
+ private_key=config["private_key"],
130
+ api_url=config["api_url"],
131
+ chain=config["chain"],
132
+ ),
133
+ "xache_collective_query": partial(
134
+ collective_query,
135
+ wallet_address=config["wallet_address"],
136
+ private_key=config["private_key"],
137
+ api_url=config["api_url"],
138
+ chain=config["chain"],
139
+ ),
140
+ "xache_check_reputation": partial(
141
+ check_reputation,
142
+ wallet_address=config["wallet_address"],
143
+ private_key=config["private_key"],
144
+ api_url=config["api_url"],
145
+ chain=config["chain"],
146
+ ),
147
+ }
148
+
149
+ def _register_xache_functions(self):
150
+ """Register Xache functions as executable"""
151
+ for name, func in self._xache_function_map.items():
152
+ self.register_function(
153
+ function_map={name: func}
154
+ )
155
+
156
+ def execute_function(self, func_call: Dict[str, Any]) -> Any:
157
+ """Execute a function call"""
158
+ name = func_call.get("name")
159
+ args = func_call.get("arguments", {})
160
+
161
+ if name in self._xache_function_map:
162
+ return self._xache_function_map[name](**args)
163
+
164
+ return super().execute_function(func_call)
165
+
166
+
167
+ class XacheAssistantAgent(AssistantAgent):
168
+ """
169
+ AutoGen AssistantAgent with Xache capabilities.
170
+
171
+ Extends AssistantAgent with persistent memory and collective intelligence.
172
+
173
+ Example:
174
+ ```python
175
+ from xache_autogen import XacheAssistantAgent
176
+
177
+ assistant = XacheAssistantAgent(
178
+ name="assistant",
179
+ wallet_address="0x...",
180
+ private_key="0x...",
181
+ llm_config={"model": "gpt-4"}
182
+ )
183
+
184
+ # Use in conversation
185
+ user_proxy.initiate_chat(assistant, message="Research quantum computing")
186
+ ```
187
+ """
188
+
189
+ def __init__(
190
+ self,
191
+ name: str,
192
+ wallet_address: str,
193
+ private_key: str,
194
+ api_url: Optional[str] = None,
195
+ chain: str = "base",
196
+ system_message: Optional[str] = None,
197
+ llm_config: Optional[Dict] = None,
198
+ timeout: int = 30000,
199
+ debug: bool = False,
200
+ **kwargs
201
+ ):
202
+ # Build xache config with env-based default
203
+ resolved_api_url = api_url or os.environ.get("XACHE_API_URL", "https://api.xache.xyz")
204
+ self._xache_config = {
205
+ "wallet_address": wallet_address,
206
+ "private_key": private_key,
207
+ "api_url": resolved_api_url,
208
+ "chain": chain,
209
+ "timeout": timeout,
210
+ "debug": debug,
211
+ }
212
+
213
+ # Create bound function map
214
+ self._xache_function_map = self._create_function_map()
215
+
216
+ # Add Xache functions to llm_config (with deduplication)
217
+ if llm_config is None:
218
+ llm_config = {}
219
+
220
+ if "functions" not in llm_config:
221
+ llm_config["functions"] = []
222
+
223
+ # Deduplicate: only add xache functions that aren't already present
224
+ existing_names = {f.get("name") for f in llm_config["functions"]}
225
+ for func in xache_functions:
226
+ if func.get("name") not in existing_names:
227
+ llm_config["functions"].append(func)
228
+ existing_names.add(func.get("name"))
229
+
230
+ # Default system message
231
+ if system_message is None:
232
+ system_message = (
233
+ "You are a helpful AI assistant with persistent memory through "
234
+ "Xache Protocol. You can:\n"
235
+ "- Store important information with xache_memory_store\n"
236
+ "- Retrieve past memories with xache_memory_retrieve\n"
237
+ "- Contribute insights with xache_collective_contribute\n"
238
+ "- Learn from others with xache_collective_query\n"
239
+ "- Check reputation with xache_check_reputation\n\n"
240
+ "Use these capabilities to maintain context across conversations "
241
+ "and contribute to collective knowledge."
242
+ )
243
+
244
+ super().__init__(
245
+ name=name,
246
+ system_message=system_message,
247
+ llm_config=llm_config,
248
+ **kwargs
249
+ )
250
+
251
+ # Register function executors
252
+ self._register_xache_functions()
253
+
254
+ def _create_function_map(self) -> Dict[str, Callable]:
255
+ """Create bound functions with Xache config"""
256
+ config = self._xache_config
257
+ return {
258
+ "xache_memory_store": partial(
259
+ memory_store,
260
+ wallet_address=config["wallet_address"],
261
+ private_key=config["private_key"],
262
+ api_url=config["api_url"],
263
+ chain=config["chain"],
264
+ ),
265
+ "xache_memory_retrieve": partial(
266
+ memory_retrieve,
267
+ wallet_address=config["wallet_address"],
268
+ private_key=config["private_key"],
269
+ api_url=config["api_url"],
270
+ chain=config["chain"],
271
+ ),
272
+ "xache_collective_contribute": partial(
273
+ collective_contribute,
274
+ wallet_address=config["wallet_address"],
275
+ private_key=config["private_key"],
276
+ api_url=config["api_url"],
277
+ chain=config["chain"],
278
+ ),
279
+ "xache_collective_query": partial(
280
+ collective_query,
281
+ wallet_address=config["wallet_address"],
282
+ private_key=config["private_key"],
283
+ api_url=config["api_url"],
284
+ chain=config["chain"],
285
+ ),
286
+ "xache_check_reputation": partial(
287
+ check_reputation,
288
+ wallet_address=config["wallet_address"],
289
+ private_key=config["private_key"],
290
+ api_url=config["api_url"],
291
+ chain=config["chain"],
292
+ ),
293
+ }
294
+
295
+ def _register_xache_functions(self):
296
+ """Register Xache functions as executable"""
297
+ for name, func in self._xache_function_map.items():
298
+ self.register_function(
299
+ function_map={name: func}
300
+ )
@@ -0,0 +1,393 @@
1
+ """
2
+ Xache Functions for AutoGen
3
+ Function definitions that can be registered with AutoGen agents
4
+ """
5
+
6
+ import os
7
+ from typing import Any, Dict, List, Optional, Callable
8
+
9
+ from xache import XacheClient
10
+ from ._async_utils import run_sync
11
+
12
+
13
+ def create_xache_client(
14
+ wallet_address: str,
15
+ private_key: str,
16
+ api_url: Optional[str] = None,
17
+ chain: str = "base",
18
+ ) -> XacheClient:
19
+ """Create an Xache client instance"""
20
+ chain_prefix = "sol" if chain == "solana" else "evm"
21
+ did = f"did:agent:{chain_prefix}:{wallet_address.lower()}"
22
+ resolved_api_url = api_url or os.environ.get("XACHE_API_URL", "https://api.xache.xyz")
23
+ return XacheClient(
24
+ api_url=resolved_api_url,
25
+ did=did,
26
+ private_key=private_key,
27
+ )
28
+
29
+
30
+ def memory_store(
31
+ content: str,
32
+ context: str,
33
+ tags: Optional[List[str]] = None,
34
+ *,
35
+ wallet_address: str,
36
+ private_key: str,
37
+ api_url: Optional[str] = None,
38
+ chain: str = "base",
39
+ ) -> Dict[str, Any]:
40
+ """
41
+ Store a memory with cryptographic receipt.
42
+
43
+ Args:
44
+ content: The content to store
45
+ context: Context/category for the memory
46
+ tags: Optional tags for categorization
47
+ wallet_address: Wallet address for authentication
48
+ private_key: Private key for signing
49
+ api_url: Xache API URL
50
+ chain: Chain to use ('base' or 'solana')
51
+
52
+ Returns:
53
+ Dict with memoryId and receiptId
54
+ """
55
+ client = create_xache_client(wallet_address, private_key, api_url, chain)
56
+
57
+ async def _store():
58
+ async with client as c:
59
+ result = await c.memory.store(
60
+ content=content,
61
+ context=context,
62
+ tags=tags or [],
63
+ )
64
+ return result
65
+
66
+ result = run_sync(_store())
67
+
68
+ return {
69
+ "memoryId": result.get("memoryId"),
70
+ "receiptId": result.get("receiptId"),
71
+ "message": f"Stored memory in context '{context}'"
72
+ }
73
+
74
+
75
+ def memory_retrieve(
76
+ query: str,
77
+ context: Optional[str] = None,
78
+ limit: int = 5,
79
+ *,
80
+ wallet_address: str,
81
+ private_key: str,
82
+ api_url: Optional[str] = None,
83
+ chain: str = "base",
84
+ ) -> Dict[str, Any]:
85
+ """
86
+ Retrieve memories by semantic search.
87
+
88
+ Args:
89
+ query: Search query
90
+ context: Optional context filter
91
+ limit: Maximum number of results
92
+ wallet_address: Wallet address for authentication
93
+ private_key: Private key for signing
94
+ api_url: Xache API URL
95
+ chain: Chain to use ('base' or 'solana')
96
+
97
+ Returns:
98
+ Dict with memories list
99
+ """
100
+ client = create_xache_client(wallet_address, private_key, api_url, chain)
101
+
102
+ async def _retrieve():
103
+ async with client as c:
104
+ result = await c.memory.retrieve(
105
+ query=query,
106
+ context=context,
107
+ limit=limit,
108
+ )
109
+ return result
110
+
111
+ result = run_sync(_retrieve())
112
+
113
+ # Defensive type checking
114
+ memories = result.get("memories", []) if isinstance(result, dict) else []
115
+ return {
116
+ "count": len(memories),
117
+ "memories": [
118
+ {
119
+ "content": m.get("content"),
120
+ "context": m.get("context"),
121
+ "relevance": m.get("relevance"),
122
+ }
123
+ for m in memories
124
+ ]
125
+ }
126
+
127
+
128
+ def collective_contribute(
129
+ insight: str,
130
+ domain: str,
131
+ evidence: Optional[str] = None,
132
+ tags: Optional[List[str]] = None,
133
+ *,
134
+ wallet_address: str,
135
+ private_key: str,
136
+ api_url: Optional[str] = None,
137
+ chain: str = "base",
138
+ ) -> Dict[str, Any]:
139
+ """
140
+ Contribute an insight to collective intelligence.
141
+
142
+ Args:
143
+ insight: The insight to contribute
144
+ domain: Domain/topic of the insight
145
+ evidence: Optional supporting evidence
146
+ tags: Optional tags
147
+ wallet_address: Wallet address for authentication
148
+ private_key: Private key for signing
149
+ api_url: Xache API URL
150
+ chain: Chain to use ('base' or 'solana')
151
+
152
+ Returns:
153
+ Dict with heuristicId and receiptId
154
+ """
155
+ client = create_xache_client(wallet_address, private_key, api_url, chain)
156
+
157
+ async def _contribute():
158
+ async with client as c:
159
+ result = await c.collective.contribute(
160
+ domain=domain,
161
+ pattern=insight,
162
+ evidence=evidence,
163
+ tags=tags or [],
164
+ )
165
+ return result
166
+
167
+ result = run_sync(_contribute())
168
+
169
+ return {
170
+ "heuristicId": result.get("heuristicId"),
171
+ "receiptId": result.get("receiptId"),
172
+ "message": f"Contributed insight to domain '{domain}'"
173
+ }
174
+
175
+
176
+ def collective_query(
177
+ query: str,
178
+ domain: Optional[str] = None,
179
+ limit: int = 5,
180
+ *,
181
+ wallet_address: str,
182
+ private_key: str,
183
+ api_url: Optional[str] = None,
184
+ chain: str = "base",
185
+ ) -> Dict[str, Any]:
186
+ """
187
+ Query collective intelligence for insights.
188
+
189
+ Args:
190
+ query: Search query
191
+ domain: Optional domain filter
192
+ limit: Maximum number of results
193
+ wallet_address: Wallet address for authentication
194
+ private_key: Private key for signing
195
+ api_url: Xache API URL
196
+ chain: Chain to use ('base' or 'solana')
197
+
198
+ Returns:
199
+ Dict with insights list
200
+ """
201
+ client = create_xache_client(wallet_address, private_key, api_url, chain)
202
+
203
+ async def _query():
204
+ async with client as c:
205
+ result = await c.collective.query(
206
+ query=query,
207
+ domain=domain,
208
+ limit=limit,
209
+ )
210
+ return result
211
+
212
+ result = run_sync(_query())
213
+
214
+ # Defensive type checking
215
+ results = result.get("results", []) if isinstance(result, dict) else []
216
+ return {
217
+ "count": len(results),
218
+ "insights": [
219
+ {
220
+ "pattern": r.get("pattern"),
221
+ "domain": r.get("domain"),
222
+ "relevance": r.get("relevance"),
223
+ }
224
+ for r in results
225
+ ]
226
+ }
227
+
228
+
229
+ def check_reputation(
230
+ agent_did: Optional[str] = None,
231
+ *,
232
+ wallet_address: str,
233
+ private_key: str,
234
+ api_url: Optional[str] = None,
235
+ chain: str = "base",
236
+ ) -> Dict[str, Any]:
237
+ """
238
+ Check reputation score.
239
+
240
+ Args:
241
+ agent_did: Optional DID to check (defaults to own reputation)
242
+ wallet_address: Wallet address for authentication
243
+ private_key: Private key for signing
244
+ api_url: Xache API URL
245
+ chain: Chain to use ('base' or 'solana')
246
+
247
+ Returns:
248
+ Dict with reputation info
249
+ """
250
+ client = create_xache_client(wallet_address, private_key, api_url, chain)
251
+
252
+ async def _check():
253
+ async with client as c:
254
+ if agent_did:
255
+ result = await c.reputation.get_score(agent_did=agent_did)
256
+ else:
257
+ result = await c.reputation.get_score()
258
+ return result
259
+
260
+ result = run_sync(_check())
261
+
262
+ score = result.get("score", 0)
263
+
264
+ # Determine level
265
+ if score >= 0.9:
266
+ level = "Elite"
267
+ elif score >= 0.7:
268
+ level = "Trusted"
269
+ elif score >= 0.5:
270
+ level = "Established"
271
+ elif score >= 0.3:
272
+ level = "Developing"
273
+ else:
274
+ level = "New"
275
+
276
+ return {
277
+ "score": score,
278
+ "level": level,
279
+ "erc8004Enabled": bool(result.get("erc8004AgentId")),
280
+ "erc8004AgentId": result.get("erc8004AgentId"),
281
+ }
282
+
283
+
284
+ # Function schemas for AutoGen
285
+ xache_functions = [
286
+ {
287
+ "name": "xache_memory_store",
288
+ "description": "Store a memory with cryptographic receipt. Use this for important information that should persist across sessions.",
289
+ "parameters": {
290
+ "type": "object",
291
+ "properties": {
292
+ "content": {
293
+ "type": "string",
294
+ "description": "The content to store"
295
+ },
296
+ "context": {
297
+ "type": "string",
298
+ "description": "Context/category for the memory (e.g., 'research', 'conversation')"
299
+ },
300
+ "tags": {
301
+ "type": "array",
302
+ "items": {"type": "string"},
303
+ "description": "Optional tags for categorization"
304
+ }
305
+ },
306
+ "required": ["content", "context"]
307
+ }
308
+ },
309
+ {
310
+ "name": "xache_memory_retrieve",
311
+ "description": "Retrieve memories by semantic search. Use this to recall information from previous sessions.",
312
+ "parameters": {
313
+ "type": "object",
314
+ "properties": {
315
+ "query": {
316
+ "type": "string",
317
+ "description": "What to search for"
318
+ },
319
+ "context": {
320
+ "type": "string",
321
+ "description": "Optional context filter"
322
+ },
323
+ "limit": {
324
+ "type": "integer",
325
+ "description": "Maximum number of results (default: 5)"
326
+ }
327
+ },
328
+ "required": ["query"]
329
+ }
330
+ },
331
+ {
332
+ "name": "xache_collective_contribute",
333
+ "description": "Contribute an insight to the collective intelligence pool. Use this when you discover something valuable that could help other agents.",
334
+ "parameters": {
335
+ "type": "object",
336
+ "properties": {
337
+ "insight": {
338
+ "type": "string",
339
+ "description": "The insight to contribute"
340
+ },
341
+ "domain": {
342
+ "type": "string",
343
+ "description": "Domain/topic of the insight"
344
+ },
345
+ "evidence": {
346
+ "type": "string",
347
+ "description": "Optional supporting evidence"
348
+ },
349
+ "tags": {
350
+ "type": "array",
351
+ "items": {"type": "string"},
352
+ "description": "Optional tags"
353
+ }
354
+ },
355
+ "required": ["insight", "domain"]
356
+ }
357
+ },
358
+ {
359
+ "name": "xache_collective_query",
360
+ "description": "Query the collective intelligence pool for insights from other agents.",
361
+ "parameters": {
362
+ "type": "object",
363
+ "properties": {
364
+ "query": {
365
+ "type": "string",
366
+ "description": "What to search for"
367
+ },
368
+ "domain": {
369
+ "type": "string",
370
+ "description": "Optional domain filter"
371
+ },
372
+ "limit": {
373
+ "type": "integer",
374
+ "description": "Maximum number of results (default: 5)"
375
+ }
376
+ },
377
+ "required": ["query"]
378
+ }
379
+ },
380
+ {
381
+ "name": "xache_check_reputation",
382
+ "description": "Check reputation score and ERC-8004 status. Higher reputation means lower costs and more trust.",
383
+ "parameters": {
384
+ "type": "object",
385
+ "properties": {
386
+ "agent_did": {
387
+ "type": "string",
388
+ "description": "Optional DID to check (defaults to own reputation)"
389
+ }
390
+ }
391
+ }
392
+ }
393
+ ]
@@ -0,0 +1,243 @@
1
+ """
2
+ Xache Conversation Memory for AutoGen
3
+ Persistent storage for conversation history and context
4
+ """
5
+
6
+ import os
7
+ import uuid
8
+ from typing import Any, Dict, List, Optional
9
+
10
+ from xache import XacheClient
11
+ from ._async_utils import run_sync
12
+
13
+
14
+ class XacheConversationMemory:
15
+ """
16
+ Persistent conversation memory backed by Xache.
17
+
18
+ Stores conversation history with cryptographic receipts for
19
+ verification and persistence across sessions.
20
+
21
+ Example:
22
+ ```python
23
+ from xache_autogen import XacheConversationMemory
24
+
25
+ memory = XacheConversationMemory(
26
+ wallet_address="0x...",
27
+ private_key="0x...",
28
+ conversation_id="unique-id"
29
+ )
30
+
31
+ # Store conversation turn
32
+ memory.add_message("user", "Hello!")
33
+ memory.add_message("assistant", "Hi there!")
34
+
35
+ # Retrieve history
36
+ history = memory.get_history()
37
+
38
+ # Summarize and store
39
+ memory.store_summary("User greeted, assistant responded.")
40
+ ```
41
+ """
42
+
43
+ def __init__(
44
+ self,
45
+ wallet_address: str,
46
+ private_key: str,
47
+ conversation_id: Optional[str] = None,
48
+ api_url: Optional[str] = None,
49
+ chain: str = "base",
50
+ ):
51
+ self.wallet_address = wallet_address
52
+ self.api_url = api_url or os.environ.get("XACHE_API_URL", "https://api.xache.xyz")
53
+ self.chain = chain
54
+ # Use UUID for collision-resistant conversation ID
55
+ self.conversation_id = conversation_id or f"autogen-{uuid.uuid4()}"
56
+
57
+ chain_prefix = "sol" if chain == "solana" else "evm"
58
+ self.did = f"did:agent:{chain_prefix}:{wallet_address.lower()}"
59
+
60
+ self._client = XacheClient(
61
+ api_url=self.api_url,
62
+ did=self.did,
63
+ private_key=private_key,
64
+ )
65
+
66
+ # Local message buffer
67
+ self._messages: List[Dict[str, str]] = []
68
+
69
+ def add_message(self, role: str, content: str, metadata: Optional[Dict] = None):
70
+ """
71
+ Add a message to the conversation.
72
+
73
+ Args:
74
+ role: Message role (user, assistant, system)
75
+ content: Message content
76
+ metadata: Optional metadata
77
+ """
78
+ import json
79
+ import time
80
+
81
+ message = {
82
+ "role": role,
83
+ "content": content,
84
+ "timestamp": time.time(),
85
+ }
86
+ self._messages.append(message)
87
+
88
+ # Store to Xache
89
+ async def _store():
90
+ async with self._client as client:
91
+ result = await client.memory.store(
92
+ content=json.dumps(message),
93
+ context=f"autogen:conversation:{self.conversation_id}",
94
+ tags=["autogen", "conversation", role],
95
+ metadata={
96
+ "conversationId": self.conversation_id,
97
+ "role": role,
98
+ **(metadata or {}),
99
+ },
100
+ )
101
+ return result
102
+
103
+ run_sync(_store())
104
+
105
+ def get_history(self, limit: int = 50) -> List[Dict[str, str]]:
106
+ """
107
+ Get conversation history from remote and update local cache.
108
+
109
+ Args:
110
+ limit: Maximum messages to retrieve
111
+
112
+ Returns:
113
+ List of messages
114
+ """
115
+ import json
116
+
117
+ async def _retrieve():
118
+ async with self._client as client:
119
+ result = await client.memory.retrieve(
120
+ context=f"autogen:conversation:{self.conversation_id}",
121
+ limit=limit,
122
+ )
123
+ return result
124
+
125
+ result = run_sync(_retrieve())
126
+
127
+ # Defensive type checking
128
+ memories = result.get("memories", []) if isinstance(result, dict) else []
129
+
130
+ messages = []
131
+ for m in memories:
132
+ try:
133
+ msg = json.loads(m.get("content", "{}"))
134
+ messages.append(msg)
135
+ except json.JSONDecodeError:
136
+ pass
137
+
138
+ # Sort by timestamp
139
+ messages.sort(key=lambda x: x.get("timestamp", 0))
140
+
141
+ # Sync local cache with remote
142
+ self._messages = messages
143
+
144
+ return messages
145
+
146
+ def refresh(self) -> List[Dict[str, str]]:
147
+ """
148
+ Refresh local cache from remote storage.
149
+
150
+ Returns:
151
+ Updated list of messages
152
+ """
153
+ return self.get_history()
154
+
155
+ def store_summary(self, summary: str, metadata: Optional[Dict] = None) -> str:
156
+ """
157
+ Store a conversation summary.
158
+
159
+ Args:
160
+ summary: Summary text
161
+ metadata: Optional metadata
162
+
163
+ Returns:
164
+ Memory ID
165
+ """
166
+
167
+ async def _store():
168
+ async with self._client as client:
169
+ result = await client.memory.store(
170
+ content=summary,
171
+ context=f"autogen:summary:{self.conversation_id}",
172
+ tags=["autogen", "summary"],
173
+ metadata={
174
+ "conversationId": self.conversation_id,
175
+ "messageCount": len(self._messages),
176
+ **(metadata or {}),
177
+ },
178
+ )
179
+ return result
180
+
181
+ result = run_sync(_store())
182
+
183
+ return result.get("memoryId", "")
184
+
185
+ def search(self, query: str, limit: int = 5) -> List[Dict]:
186
+ """
187
+ Search conversation history.
188
+
189
+ Args:
190
+ query: Search query
191
+ limit: Maximum results
192
+
193
+ Returns:
194
+ List of matching memories
195
+ """
196
+
197
+ async def _search():
198
+ async with self._client as client:
199
+ result = await client.memory.retrieve(
200
+ query=query,
201
+ context=f"autogen:conversation:{self.conversation_id}",
202
+ limit=limit,
203
+ )
204
+ return result
205
+
206
+ result = run_sync(_search())
207
+
208
+ # Defensive type checking
209
+ if isinstance(result, dict):
210
+ return result.get("memories", [])
211
+ return []
212
+
213
+ def clear_local(self):
214
+ """Clear local message buffer (doesn't delete from Xache)"""
215
+ self._messages = []
216
+
217
+ @property
218
+ def messages(self) -> List[Dict[str, str]]:
219
+ """Get local message buffer"""
220
+ return self._messages
221
+
222
+ def format_for_prompt(self, max_messages: int = 10) -> str:
223
+ """
224
+ Format recent history for inclusion in prompt.
225
+
226
+ Args:
227
+ max_messages: Maximum messages to include
228
+
229
+ Returns:
230
+ Formatted string
231
+ """
232
+ recent = self._messages[-max_messages:] if self._messages else []
233
+
234
+ if not recent:
235
+ return ""
236
+
237
+ lines = []
238
+ for msg in recent:
239
+ role = msg.get("role", "unknown").capitalize()
240
+ content = msg.get("content", "")
241
+ lines.append(f"{role}: {content}")
242
+
243
+ return "\n".join(lines)