solana-agent 20.0.0__py3-none-any.whl → 20.1.4__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.
@@ -11,6 +11,7 @@ from typing import AsyncGenerator, Dict, Any, Literal, Optional, Union
11
11
  from solana_agent.factories.agent_factory import SolanaAgentFactory
12
12
  from solana_agent.interfaces.client.client import SolanaAgent as SolanaAgentInterface
13
13
  from solana_agent.interfaces.plugins.plugins import Tool
14
+ from solana_agent.interfaces.services.routing import RoutingService as RoutingInterface
14
15
 
15
16
 
16
17
  class SolanaAgent(SolanaAgentInterface):
@@ -54,6 +55,7 @@ class SolanaAgent(SolanaAgentInterface):
54
55
  audio_input_format: Literal[
55
56
  "flac", "mp3", "mp4", "mpeg", "mpga", "m4a", "ogg", "wav", "webm"
56
57
  ] = "mp4",
58
+ router: Optional[RoutingInterface] = None,
57
59
  ) -> AsyncGenerator[Union[str, bytes], None]: # pragma: no cover
58
60
  """Process a user message and return the response stream.
59
61
 
@@ -63,9 +65,10 @@ class SolanaAgent(SolanaAgentInterface):
63
65
  prompt: Optional prompt for the agent
64
66
  output_format: Response format ("text" or "audio")
65
67
  audio_voice: Voice to use for audio output
66
- audio_instructions: Optional instructions for audio synthesis
68
+ audio_instructions: Not used currently
67
69
  audio_output_format: Audio output format
68
70
  audio_input_format: Audio input format
71
+ router: Optional routing service for processing
69
72
 
70
73
  Returns:
71
74
  Async generator yielding response chunks (text strings or audio bytes)
@@ -79,6 +82,7 @@ class SolanaAgent(SolanaAgentInterface):
79
82
  audio_output_format=audio_output_format,
80
83
  audio_input_format=audio_input_format,
81
84
  prompt=prompt,
85
+ router=router,
82
86
  ):
83
87
  yield chunk
84
88
 
@@ -6,11 +6,10 @@ class RoutingService(ABC):
6
6
  """Interface for query routing services."""
7
7
 
8
8
  @abstractmethod
9
- async def route_query(self, query: str) -> Tuple[str, Any]:
9
+ async def route_query(self, query: str) -> str:
10
10
  """Route a query to the appropriate agent.
11
11
 
12
12
  Args:
13
- user_id: User ID
14
13
  query: User query
15
14
 
16
15
  Returns:
@@ -12,7 +12,6 @@ from typing import AsyncGenerator, Dict, List, Literal, Optional, Any, Union
12
12
 
13
13
  from solana_agent.interfaces.services.agent import AgentService as AgentServiceInterface
14
14
  from solana_agent.interfaces.providers.llm import LLMProvider
15
- from solana_agent.interfaces.plugins.plugins import ToolRegistry as ToolRegistryInterface
16
15
  from solana_agent.plugins.manager import PluginManager
17
16
  from solana_agent.plugins.registry import ToolRegistry
18
17
  from solana_agent.domains.agent import AIAgent, BusinessMission
@@ -8,6 +8,7 @@ clean separation of concerns.
8
8
  from typing import Any, AsyncGenerator, Dict, Literal, Optional, Union
9
9
 
10
10
  from solana_agent.interfaces.services.query import QueryService as QueryServiceInterface
11
+ from solana_agent.interfaces.services.routing import RoutingService as RoutingServiceInterface
11
12
  from solana_agent.services.agent import AgentService
12
13
  from solana_agent.services.routing import RoutingService
13
14
  from solana_agent.interfaces.providers.memory import MemoryProvider
@@ -47,6 +48,7 @@ class QueryService(QueryServiceInterface):
47
48
  "flac", "mp3", "mp4", "mpeg", "mpga", "m4a", "ogg", "wav", "webm"
48
49
  ] = "mp4",
49
50
  prompt: Optional[str] = None,
51
+ router: Optional[RoutingServiceInterface] = None,
50
52
  ) -> AsyncGenerator[Union[str, bytes], None]: # pragma: no cover
51
53
  """Process the user request with appropriate agent.
52
54
 
@@ -59,6 +61,7 @@ class QueryService(QueryServiceInterface):
59
61
  audio_output_format: Audio output format
60
62
  audio_input_format: Audio input format
61
63
  prompt: Optional prompt for the agent
64
+ router: Optional routing service for processing
62
65
 
63
66
  Yields:
64
67
  Response chunks (text strings or audio bytes)
@@ -96,7 +99,11 @@ class QueryService(QueryServiceInterface):
96
99
  memory_context = await self.memory_provider.retrieve(user_id)
97
100
 
98
101
  # Route query to appropriate agent
99
- agent_name = await self.routing_service.route_query(user_text)
102
+ if router:
103
+ agent_name = await router.route_query(user_text)
104
+ else:
105
+ agent_name = await self.routing_service.route_query(user_text)
106
+
100
107
  print(f"Routed to agent: {agent_name}")
101
108
 
102
109
  # Generate response
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: solana-agent
3
- Version: 20.0.0
3
+ Version: 20.1.4
4
4
  Summary: Agentic IQ
5
5
  License: MIT
6
6
  Keywords: ai,openai,ai agents,agi
@@ -48,6 +48,7 @@ Build your AI business in three lines of code!
48
48
  * Extensible Tooling
49
49
  * Simple Business Definition
50
50
  * Tested & Secure
51
+ * Support for MCP Servers
51
52
  * Built in Python
52
53
  * Deployed by [CometHeart](https://cometheart.com) & [WalletBubbles](https://walletbubbles.com)
53
54
 
@@ -56,11 +57,12 @@ Build your AI business in three lines of code!
56
57
  * Seamless text and audio streaming with real-time multi-modal processing
57
58
  * Persistent memory that preserves context across all agent interactions
58
59
  * Streamlined message history for all agent interactions
59
- * Intelligent query routing to agents with optimal domain expertise
60
+ * Intelligent query routing to agents with optimal domain expertise or your own custom routing
60
61
  * Unified value system ensuring brand-aligned agent responses
61
62
  * Powerful tool integration using standard Python packages and/or inline classes
62
63
  * Assigned tools are utilized by agents automatically and effectively
63
64
  * Simple business definition using JSON
65
+ * Ability to access any MCP server via a URL
64
66
 
65
67
  ## Stack
66
68
 
@@ -75,13 +77,13 @@ You can install Solana Agent using pip:
75
77
 
76
78
  `pip install solana-agent`
77
79
 
78
- ## Basic Usage
80
+ ## Usage
79
81
 
80
- ```python
81
- from solana_agent import SolanaAgent
82
+ ### Business Alignment Config - Optional
82
83
 
84
+ ```python
83
85
  config = {
84
- "business": { # optional
86
+ "business": {
85
87
  "mission": "To provide users with a one-stop shop for their queries.",
86
88
  "values": {
87
89
  "Friendliness": "Users must be treated fairly, openly, and with friendliness.",
@@ -92,14 +94,37 @@ config = {
92
94
  ],
93
95
  "voice": "The voice of the brand is that of a research business."
94
96
  },
95
- "mongo": { # optional
97
+ }
98
+ ```
99
+
100
+ ### Conversational History Config - Optional
101
+
102
+ ```python
103
+ config = {
104
+ "mongo": {
96
105
  "connection_string": "mongodb://localhost:27017",
97
106
  "database": "solana_agent"
98
107
  },
99
- "zep": { # optional
108
+ }
109
+ ```
110
+
111
+ ### Conversational Memory Config - Optional
112
+
113
+ ```python
114
+ config = {
115
+ "zep": {
100
116
  "api_key": "your-zep-api-key",
101
117
  "base_url": "your-zep-base-url", # not applicable if using Zep Cloud
102
118
  },
119
+ }
120
+ ```
121
+
122
+ ### Text/Text Streaming
123
+
124
+ ```python
125
+ from solana_agent import SolanaAgent
126
+
127
+ config = {
103
128
  "openai": {
104
129
  "api_key": "your-openai-api-key",
105
130
  },
@@ -123,40 +148,110 @@ async for response in solana_agent.process("user123", "What are the latest AI de
123
148
  print(response, end="")
124
149
  ```
125
150
 
126
- ## Plugin Usage
151
+ ### Audio/Audio Streaming
127
152
 
128
- Plugins like Solana Agent Kit (sakit) integrate automatically with Solana Agent.
153
+ ```python
154
+ from solana_agent import SolanaAgent
129
155
 
130
- `pip install sakit`
156
+ config = {
157
+ "openai": {
158
+ "api_key": "your-openai-api-key",
159
+ },
160
+ "agents": [
161
+ {
162
+ "name": "research_specialist",
163
+ "instructions": "You are an expert researcher who synthesizes complex information clearly.",
164
+ "specialization": "Research and knowledge synthesis",
165
+ },
166
+ {
167
+ "name": "customer_support",
168
+ "instructions": "You provide friendly, helpful customer support responses.",
169
+ "specialization": "Customer inquiries",
170
+ }
171
+ ],
172
+ }
173
+
174
+ solana_agent = SolanaAgent(config=config)
175
+
176
+ audio_content = audio_file.read()
177
+
178
+ async for response in solana_agent.process("user123", audio_content, output_format="audio", audio_voice="nova", audio_input_format="webm", audio_output_format="aac"):
179
+ print(response, end="")
180
+ ```
181
+
182
+ ### Text/Audio Streaming
131
183
 
132
184
  ```python
133
185
  from solana_agent import SolanaAgent
134
186
 
135
187
  config = {
136
- "business": { # optional
137
- "mission": "To provide users with a one-stop shop for their queries.",
138
- "values": {
139
- "Friendliness": "Users must be treated fairly, openly, and with friendliness.",
140
- "Ethical": "Agents must use a strong ethical framework in their interactions with users.",
141
- },
142
- "goals": [
143
- "Empower users with great answers to their queries.",
144
- ],
145
- "voice": "The voice of the brand is that of a research business."
146
- },
147
- "openai": { # optional
188
+ "openai": {
148
189
  "api_key": "your-openai-api-key",
149
190
  },
150
- "ollama": { # optional
151
- "url": "your-ollama-url",
152
- },
153
- "mongo": { # optional
154
- "connection_string": "mongodb://localhost:27017",
155
- "database": "solana_agent"
191
+ "agents": [
192
+ {
193
+ "name": "research_specialist",
194
+ "instructions": "You are an expert researcher who synthesizes complex information clearly.",
195
+ "specialization": "Research and knowledge synthesis",
196
+ },
197
+ {
198
+ "name": "customer_support",
199
+ "instructions": "You provide friendly, helpful customer support responses.",
200
+ "specialization": "Customer inquiries",
201
+ }
202
+ ],
203
+ }
204
+
205
+ solana_agent = SolanaAgent(config=config)
206
+
207
+ async for response in solana_agent.process("user123", "What is the latest news on Elon Musk?", output_format="audio", audio_voice="nova", audio_output_format="aac"):
208
+ print(response, end="")
209
+ ```
210
+
211
+ ### Audio/Text Streaming
212
+
213
+ ```python
214
+ from solana_agent import SolanaAgent
215
+
216
+ config = {
217
+ "openai": {
218
+ "api_key": "your-openai-api-key",
156
219
  },
157
- "zep": { # optional
158
- "api_key": "your-zep-api-key",
159
- "base_url": "your-zep-base-url", # not applicable if using Zep Cloud
220
+ "agents": [
221
+ {
222
+ "name": "research_specialist",
223
+ "instructions": "You are an expert researcher who synthesizes complex information clearly.",
224
+ "specialization": "Research and knowledge synthesis",
225
+ },
226
+ {
227
+ "name": "customer_support",
228
+ "instructions": "You provide friendly, helpful customer support responses.",
229
+ "specialization": "Customer inquiries",
230
+ }
231
+ ],
232
+ }
233
+
234
+ solana_agent = SolanaAgent(config=config)
235
+
236
+ audio_content = audio_file.read()
237
+
238
+ async for response in solana_agent.process("user123", audio_content, audio_input_format="aac"):
239
+ print(response, end="")
240
+ ```
241
+
242
+ ### Plugins
243
+
244
+ Plugins like Solana Agent Kit (sakit) integrate automatically with Solana Agent.
245
+
246
+ `pip install sakit`
247
+
248
+ #### Internet Search
249
+ ```python
250
+ from solana_agent import SolanaAgent
251
+
252
+ config = {
253
+ "openai": {
254
+ "api_key": "your-openai-api-key",
160
255
  },
161
256
  "tools": {
162
257
  "search_internet": {
@@ -186,9 +281,47 @@ async for response in solana_agent.process("user123", "What are the latest AI de
186
281
  print(response, end="")
187
282
  ```
188
283
 
284
+ #### MCP
285
+ ```python
286
+ from solana_agent import SolanaAgent
287
+
288
+ config = {
289
+ "openai": {
290
+ "api_key": "your-openai-api-key",
291
+ },
292
+ "tools": {
293
+ "mcp": {
294
+ "server_urls": [
295
+ "http://mcp-server1.com/mcp",
296
+ "http://mcp-server2.com/mcp",
297
+ "http://mcp-server3.com/mcp"
298
+ ]
299
+ }
300
+ },
301
+ "agents": [
302
+ {
303
+ "name": "research_specialist",
304
+ "instructions": "You are an expert researcher who synthesizes complex information clearly.",
305
+ "specialization": "Research and knowledge synthesis",
306
+ "tools": ["mcp"],
307
+ },
308
+ {
309
+ "name": "customer_support",
310
+ "instructions": "You provide friendly, helpful customer support responses.",
311
+ "specialization": "Customer inquiries",
312
+ }
313
+ ],
314
+ }
315
+
316
+ solana_agent = SolanaAgent(config=config)
317
+
318
+ async for response in solana_agent.process("user123", "What are the latest AI developments?"):
319
+ print(response, end="")
320
+ ```
321
+
189
322
  To create a plugin like Solana Agent Kit - read the [code](https://github.com/truemagic-coder/solana-agent-kit)
190
323
 
191
- ## Custom Inline Tool Usage
324
+ ### Custom Inline Tools
192
325
 
193
326
  ```python
194
327
  from solana_agent import SolanaAgent
@@ -241,31 +374,9 @@ class TestTool(Tool):
241
374
  }
242
375
 
243
376
  config = {
244
- "business": { # optional
245
- "mission": "To provide users with a one-stop shop for their queries.",
246
- "values": {
247
- "Friendliness": "Users must be treated fairly, openly, and with friendliness.",
248
- "Ethical": "Agents must use a strong ethical framework in their interactions with users.",
249
- },
250
- "goals": [
251
- "Empower users with great answers to their queries.",
252
- ],
253
- "voice": "The voice of the brand is that of a research business."
254
- },
255
- "openai": { # optional
377
+ "openai": {
256
378
  "api_key": "your-openai-api-key",
257
379
  },
258
- "ollama": { # optional
259
- "url": "your-ollama-url",
260
- },
261
- "mongo": { # optional
262
- "connection_string": "mongodb://localhost:27017",
263
- "database": "solana_agent"
264
- },
265
- "zep": { # optional
266
- "api_key": "your-zep-api-key",
267
- "base_url": "your-zep-base-url", # not applicable if using Zep Cloud
268
- },
269
380
  "agents": [
270
381
  {
271
382
  "name": "research_specialist",
@@ -290,12 +401,81 @@ async for response in solana_agent.process("user123", "What are the latest AI de
290
401
  print(response, end="")
291
402
  ```
292
403
 
404
+ ### Custom Prompt Injection at Runtime
405
+
406
+ ```python
407
+ from solana_agent import SolanaAgent
408
+
409
+ config = {
410
+ "openai": {
411
+ "api_key": "your-openai-api-key",
412
+ },
413
+ "agents": [
414
+ {
415
+ "name": "research_specialist",
416
+ "instructions": "You are an expert researcher who synthesizes complex information clearly.",
417
+ "specialization": "Research and knowledge synthesis",
418
+ },
419
+ {
420
+ "name": "customer_support",
421
+ "instructions": "You provide friendly, helpful customer support responses.",
422
+ "specialization": "Customer inquiries",
423
+ }
424
+ ],
425
+ }
426
+
427
+ solana_agent = SolanaAgent(config=config)
428
+
429
+ async for response in solana_agent.process("user123", "What are the latest AI developments?", "Always end your sentences with eh?"):
430
+ print(response, end="")
431
+ ```
432
+
433
+ ### Custom Routing
434
+
435
+ ```python
436
+ from solana_agent import SolanaAgent
437
+ from solana_agent.interfaces.services.routing import RoutingService as RoutingServiceInterface
438
+
439
+ config = {
440
+ "openai": {
441
+ "api_key": "your-openai-api-key",
442
+ },
443
+ "agents": [
444
+ {
445
+ "name": "research_specialist",
446
+ "instructions": "You are an expert researcher who synthesizes complex information clearly.",
447
+ "specialization": "Research and knowledge synthesis",
448
+ },
449
+ {
450
+ "name": "customer_support",
451
+ "instructions": "You provide friendly, helpful customer support responses.",
452
+ "specialization": "Customer inquiries",
453
+ }
454
+ ],
455
+ }
456
+
457
+ class Router(RoutingServiceInterface)
458
+ def __init__(self):
459
+ # your router initialization - delete the following pass
460
+ pass
461
+
462
+ async def route_query(self, query: str) -> str:
463
+ # a simple example to route always to customer_support agent
464
+ return "customer_support"
465
+
466
+ router = Router()
467
+
468
+ solana_agent = SolanaAgent(config=config)
469
+
470
+ async for response in solana_agent.process("user123", "What are the latest AI developments?", router=router):
471
+ print(response, end="")
472
+ ```
473
+
293
474
  ## Notes
294
475
  * Solana Agent agents can only call one tool per response.
295
476
  * Solana Agent agents choose the best tool for the job.
296
477
  * Solana Agent tools do not use OpenAI function calling.
297
478
  * Solana Agent tools are async functions.
298
- * Solana Agent will use OpenAI for audio and Ollama and for text if both config vars are set
299
479
 
300
480
  ## Local Setup
301
481
 
@@ -3,7 +3,7 @@ solana_agent/adapters/__init__.py,sha256=tiEEuuy0NF3ngc_tGEcRTt71zVI58v3dYY9RvMr
3
3
  solana_agent/adapters/llm_adapter.py,sha256=3_7whVsPSJdlzBVUBlV7RBRCCo2dMXNmlACIrCoQxQ4,5426
4
4
  solana_agent/adapters/mongodb_adapter.py,sha256=qqEFbY_v1XGyFXBmwd5HSXSSHnA9wWo-Hm1vGEyIG0k,2718
5
5
  solana_agent/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- solana_agent/client/solana_agent.py,sha256=CwUQHA76QiVmp9aNZcH1BVzD7I3LffwkvxtP5yLLmew,5003
6
+ solana_agent/client/solana_agent.py,sha256=4xXPNNcULMEIx-V-_zu2IH0tlPjQU2ZzkIqZFuxAJHY,5206
7
7
  solana_agent/domains/__init__.py,sha256=HiC94wVPRy-QDJSSRywCRrhrFfTBeHjfi5z-QfZv46U,168
8
8
  solana_agent/domains/agent.py,sha256=WTo-pEc66V6D_35cpDE-kTsw1SJM-dtylPZ7em5em7Q,2659
9
9
  solana_agent/domains/routing.py,sha256=UDlgTjUoC9xIBVYu_dnf9-KG_bBgdEXAv_UtDOrYo0w,650
@@ -17,7 +17,7 @@ solana_agent/interfaces/providers/llm.py,sha256=f58kDrvESBfIr2XoZJ-VVa8vL56qyuhk
17
17
  solana_agent/interfaces/providers/memory.py,sha256=oNOH8WZXVW8assDigIWZAWiwkxbpDiKupxA2RB6tQvQ,1010
18
18
  solana_agent/interfaces/services/agent.py,sha256=34luGrUF5FNXLhF6JXwbfOSuo_SbMOmLMywG310sMDw,2082
19
19
  solana_agent/interfaces/services/query.py,sha256=m8Uc0uXT3apSOhX3N1QjLMPk1KdJhj7HDrJjWUpDPBc,1309
20
- solana_agent/interfaces/services/routing.py,sha256=gohkt5f9uYDLpu4iDVDk9yj8js9P56R6QHSIDNylgwA,438
20
+ solana_agent/interfaces/services/routing.py,sha256=UzJC-z-Q9puTWPFGEo2_CAhIxuxP5IRnze7S66NSrsI,397
21
21
  solana_agent/plugins/__init__.py,sha256=coZdgJKq1ExOaj6qB810i3rEhbjdVlrkN76ozt_Ojgo,193
22
22
  solana_agent/plugins/manager.py,sha256=Il49hXeqvu0b02pURNNp7mY8kp9_sqpi_vJIWBW5Hc0,5044
23
23
  solana_agent/plugins/registry.py,sha256=5S0DlUQKogsg1zLiRUIGMHEmGYHtOovU-S-5W1Mwo1A,3639
@@ -26,10 +26,10 @@ solana_agent/plugins/tools/auto_tool.py,sha256=DgES_cZ6xKSf_HJpFINpvJxrjVlk5oeqa
26
26
  solana_agent/repositories/__init__.py,sha256=fP83w83CGzXLnSdq-C5wbw9EhWTYtqE2lQTgp46-X_4,163
27
27
  solana_agent/repositories/memory.py,sha256=eecl1P0fr_xFSWFKIJg99q90oCS9--ihPrMLH3G2AzM,7136
28
28
  solana_agent/services/__init__.py,sha256=ab_NXJmwYUCmCrCzuTlZ47bJZINW0Y0F5jfQ9OovidU,163
29
- solana_agent/services/agent.py,sha256=Nx3D7HrL9YRP1qI9Yzhm8HR8AXBfavFYnujXsSLdZ4A,16540
30
- solana_agent/services/query.py,sha256=4MEGR_Q2THcCCjln-IcSAw7GGNqJ1q2cyEVRx69OQ7I,10746
29
+ solana_agent/services/agent.py,sha256=MdSPIC81JNuP2hfzXNGWOnRfe7OxwYHgDVZAphVCCo8,16450
30
+ solana_agent/services/query.py,sha256=QduAeiltFTwNDlAbC_emu544U4XGNioj-OauRGt9HSY,11070
31
31
  solana_agent/services/routing.py,sha256=PMCSG5m3uLMaHMj3dxNvNfcFZaeaDi7kMr7AEBCzwDE,6499
32
- solana_agent-20.0.0.dist-info/LICENSE,sha256=BnSRc-NSFuyF2s496l_4EyrwAP6YimvxWcjPiJ0J7g4,1057
33
- solana_agent-20.0.0.dist-info/METADATA,sha256=JQWWGntl9adbkC5gSghwYANhwM7TIOMgsEZz-BDG0Pw,10961
34
- solana_agent-20.0.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
35
- solana_agent-20.0.0.dist-info/RECORD,,
32
+ solana_agent-20.1.4.dist-info/LICENSE,sha256=BnSRc-NSFuyF2s496l_4EyrwAP6YimvxWcjPiJ0J7g4,1057
33
+ solana_agent-20.1.4.dist-info/METADATA,sha256=fnqm3cRwxnmHdvW2-2H1Xlg5n-h10Tzyh3rKE3G7VnI,15083
34
+ solana_agent-20.1.4.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
35
+ solana_agent-20.1.4.dist-info/RECORD,,