solana-agent 29.2.2__py3-none-any.whl → 29.3.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.
- solana_agent/adapters/openai_adapter.py +14 -7
- solana_agent/client/solana_agent.py +7 -2
- solana_agent/interfaces/client/client.py +5 -2
- solana_agent/interfaces/providers/llm.py +2 -0
- solana_agent/interfaces/services/agent.py +5 -2
- solana_agent/interfaces/services/query.py +5 -2
- solana_agent/services/agent.py +35 -23
- solana_agent/services/query.py +9 -3
- {solana_agent-29.2.2.dist-info → solana_agent-29.3.0.dist-info}/METADATA +47 -209
- {solana_agent-29.2.2.dist-info → solana_agent-29.3.0.dist-info}/RECORD +13 -13
- {solana_agent-29.2.2.dist-info → solana_agent-29.3.0.dist-info}/LICENSE +0 -0
- {solana_agent-29.2.2.dist-info → solana_agent-29.3.0.dist-info}/WHEEL +0 -0
- {solana_agent-29.2.2.dist-info → solana_agent-29.3.0.dist-info}/entry_points.txt +0 -0
@@ -410,6 +410,8 @@ class OpenAIAdapter(LLMProvider):
|
|
410
410
|
api_key: Optional[str] = None,
|
411
411
|
base_url: Optional[str] = None,
|
412
412
|
model: Optional[str] = None,
|
413
|
+
functions: Optional[List[Dict[str, Any]]] = None,
|
414
|
+
function_call: Optional[Union[str, Dict[str, Any]]] = None,
|
413
415
|
) -> T: # pragma: no cover
|
414
416
|
"""Generate structured output using Pydantic model parsing with Instructor."""
|
415
417
|
|
@@ -431,13 +433,18 @@ class OpenAIAdapter(LLMProvider):
|
|
431
433
|
|
432
434
|
patched_client = instructor.from_openai(client, mode=Mode.TOOLS_STRICT)
|
433
435
|
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
436
|
+
create_args = {
|
437
|
+
"model": current_parse_model,
|
438
|
+
"messages": messages,
|
439
|
+
"response_model": model_class,
|
440
|
+
"max_retries": 2, # Automatically retry on validation errors
|
441
|
+
}
|
442
|
+
if functions:
|
443
|
+
create_args["tools"] = functions
|
444
|
+
if function_call:
|
445
|
+
create_args["function_call"] = function_call
|
446
|
+
|
447
|
+
response = await patched_client.chat.completions.create(**create_args)
|
441
448
|
return response
|
442
449
|
except Exception as e:
|
443
450
|
logger.warning(
|
@@ -7,7 +7,9 @@ the agent system without dealing with internal implementation details.
|
|
7
7
|
|
8
8
|
import json
|
9
9
|
import importlib.util
|
10
|
-
from typing import AsyncGenerator, Dict, Any, List, Literal, Optional, Union
|
10
|
+
from typing import AsyncGenerator, Dict, Any, List, Literal, Optional, Type, Union
|
11
|
+
|
12
|
+
from pydantic import BaseModel
|
11
13
|
|
12
14
|
from solana_agent.factories.agent_factory import SolanaAgentFactory
|
13
15
|
from solana_agent.interfaces.client.client import SolanaAgent as SolanaAgentInterface
|
@@ -69,7 +71,8 @@ class SolanaAgent(SolanaAgentInterface):
|
|
69
71
|
] = "mp4",
|
70
72
|
router: Optional[RoutingInterface] = None,
|
71
73
|
images: Optional[List[Union[str, bytes]]] = None,
|
72
|
-
|
74
|
+
output_model: Optional[Type[BaseModel]] = None,
|
75
|
+
) -> AsyncGenerator[Union[str, bytes, BaseModel], None]: # pragma: no cover
|
73
76
|
"""Process a user message (text or audio) and optional images, returning the response stream.
|
74
77
|
|
75
78
|
Args:
|
@@ -83,6 +86,7 @@ class SolanaAgent(SolanaAgentInterface):
|
|
83
86
|
audio_input_format: Audio input format
|
84
87
|
router: Optional routing service for processing
|
85
88
|
images: Optional list of image URLs (str) or image bytes.
|
89
|
+
output_model: Optional Pydantic model for structured output
|
86
90
|
|
87
91
|
Returns:
|
88
92
|
Async generator yielding response chunks (text strings or audio bytes)
|
@@ -98,6 +102,7 @@ class SolanaAgent(SolanaAgentInterface):
|
|
98
102
|
audio_input_format=audio_input_format,
|
99
103
|
prompt=prompt,
|
100
104
|
router=router,
|
105
|
+
output_model=output_model,
|
101
106
|
):
|
102
107
|
yield chunk
|
103
108
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
from abc import ABC, abstractmethod
|
2
|
-
from typing import AsyncGenerator, Dict, Any, List, Literal, Optional, Union
|
2
|
+
from typing import AsyncGenerator, Dict, Any, List, Literal, Optional, Type, Union
|
3
|
+
|
4
|
+
from pydantic import BaseModel
|
3
5
|
from solana_agent.interfaces.plugins.plugins import Tool
|
4
6
|
from solana_agent.interfaces.services.routing import RoutingService as RoutingInterface
|
5
7
|
|
@@ -35,7 +37,8 @@ class SolanaAgent(ABC):
|
|
35
37
|
] = "mp4",
|
36
38
|
router: Optional[RoutingInterface] = None,
|
37
39
|
images: Optional[List[Union[str, bytes]]] = None,
|
38
|
-
|
40
|
+
output_model: Optional[Type[BaseModel]] = None,
|
41
|
+
) -> AsyncGenerator[Union[str, bytes, BaseModel], None]:
|
39
42
|
"""Process a user message and return the response stream."""
|
40
43
|
pass
|
41
44
|
|
@@ -43,6 +43,8 @@ class LLMProvider(ABC):
|
|
43
43
|
api_key: Optional[str] = None,
|
44
44
|
base_url: Optional[str] = None,
|
45
45
|
model: Optional[str] = None,
|
46
|
+
functions: Optional[List[Dict[str, Any]]] = None,
|
47
|
+
function_call: Optional[Union[str, Dict[str, Any]]] = None,
|
46
48
|
) -> T:
|
47
49
|
"""Generate structured output using a specific model class."""
|
48
50
|
pass
|
@@ -1,5 +1,7 @@
|
|
1
1
|
from abc import ABC, abstractmethod
|
2
|
-
from typing import Any, AsyncGenerator, Dict, List, Literal, Optional, Union
|
2
|
+
from typing import Any, AsyncGenerator, Dict, List, Literal, Optional, Type, Union
|
3
|
+
|
4
|
+
from pydantic import BaseModel
|
3
5
|
|
4
6
|
from solana_agent.domains.agent import AIAgent
|
5
7
|
|
@@ -45,7 +47,8 @@ class AgentService(ABC):
|
|
45
47
|
] = "aac",
|
46
48
|
prompt: Optional[str] = None,
|
47
49
|
images: Optional[List[Union[str, bytes]]] = None,
|
48
|
-
|
50
|
+
output_model: Optional[Type[BaseModel]] = None,
|
51
|
+
) -> AsyncGenerator[Union[str, bytes, BaseModel], None]:
|
49
52
|
"""Generate a response from an agent."""
|
50
53
|
pass
|
51
54
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
from abc import ABC, abstractmethod
|
2
|
-
from typing import Any, AsyncGenerator, Dict, List, Literal, Optional, Union
|
2
|
+
from typing import Any, AsyncGenerator, Dict, List, Literal, Optional, Type, Union
|
3
|
+
|
4
|
+
from pydantic import BaseModel
|
3
5
|
|
4
6
|
from solana_agent.interfaces.services.routing import RoutingService as RoutingInterface
|
5
7
|
|
@@ -35,7 +37,8 @@ class QueryService(ABC):
|
|
35
37
|
prompt: Optional[str] = None,
|
36
38
|
router: Optional[RoutingInterface] = None,
|
37
39
|
images: Optional[List[Union[str, bytes]]] = None,
|
38
|
-
|
40
|
+
output_model: Optional[Type[BaseModel]] = None,
|
41
|
+
) -> AsyncGenerator[Union[str, bytes, BaseModel], None]:
|
39
42
|
"""Process the user request and generate a response."""
|
40
43
|
pass
|
41
44
|
|
solana_agent/services/agent.py
CHANGED
@@ -10,7 +10,9 @@ from datetime import datetime
|
|
10
10
|
import json
|
11
11
|
import logging # Add logging
|
12
12
|
import re
|
13
|
-
from typing import AsyncGenerator, Dict, List, Literal, Optional, Any, Union
|
13
|
+
from typing import AsyncGenerator, Dict, List, Literal, Optional, Any, Type, Union
|
14
|
+
|
15
|
+
from pydantic import BaseModel
|
14
16
|
|
15
17
|
from solana_agent.interfaces.services.agent import AgentService as AgentServiceInterface
|
16
18
|
from solana_agent.interfaces.providers.llm import LLMProvider
|
@@ -229,8 +231,9 @@ class AgentService(AgentServiceInterface):
|
|
229
231
|
"mp3", "opus", "aac", "flac", "wav", "pcm"
|
230
232
|
] = "aac",
|
231
233
|
prompt: Optional[str] = None,
|
232
|
-
|
233
|
-
|
234
|
+
output_model: Optional[Type[BaseModel]] = None,
|
235
|
+
) -> AsyncGenerator[Union[str, bytes, BaseModel], None]: # pragma: no cover
|
236
|
+
"""Generate a response using OpenAI function calling (tools API) or structured output."""
|
234
237
|
|
235
238
|
agent = next((a for a in self.agents if a.name == agent_name), None)
|
236
239
|
if not agent:
|
@@ -252,9 +255,7 @@ class AgentService(AgentServiceInterface):
|
|
252
255
|
system_prompt = self.get_agent_system_prompt(agent_name)
|
253
256
|
user_content = str(query)
|
254
257
|
if images:
|
255
|
-
user_content +=
|
256
|
-
"\n\n[Images attached]" # Optionally, handle images as needed
|
257
|
-
)
|
258
|
+
user_content += "\n\n[Images attached]"
|
258
259
|
|
259
260
|
# Compose the prompt for generate_text
|
260
261
|
full_prompt = ""
|
@@ -266,18 +267,33 @@ class AgentService(AgentServiceInterface):
|
|
266
267
|
full_prompt += f"USER IDENTIFIER: {user_id}"
|
267
268
|
|
268
269
|
# Get OpenAI function schemas for this agent's tools
|
269
|
-
functions = [
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
)
|
270
|
+
functions = [
|
271
|
+
{
|
272
|
+
"name": tool["name"],
|
273
|
+
"description": tool.get("description", ""),
|
274
|
+
"parameters": tool.get("parameters", {}),
|
275
|
+
}
|
276
|
+
for tool in self.get_agent_tools(agent_name)
|
277
|
+
]
|
278
278
|
|
279
|
-
response_text = ""
|
280
279
|
try:
|
280
|
+
if output_model is not None:
|
281
|
+
# --- Structured output with tool support ---
|
282
|
+
model_instance = await self.llm_provider.parse_structured_output(
|
283
|
+
prompt=full_prompt,
|
284
|
+
system_prompt=system_prompt,
|
285
|
+
model_class=output_model,
|
286
|
+
api_key=self.api_key,
|
287
|
+
base_url=self.base_url,
|
288
|
+
model=self.model,
|
289
|
+
functions=functions if functions else None,
|
290
|
+
function_call="auto" if functions else None,
|
291
|
+
)
|
292
|
+
yield model_instance
|
293
|
+
return
|
294
|
+
|
295
|
+
# --- Streaming text/audio with tool support (as before) ---
|
296
|
+
response_text = ""
|
281
297
|
while True:
|
282
298
|
response = await self.llm_provider.generate_text(
|
283
299
|
prompt=full_prompt,
|
@@ -298,9 +314,7 @@ class AgentService(AgentServiceInterface):
|
|
298
314
|
break
|
299
315
|
|
300
316
|
choice = response.choices[0]
|
301
|
-
message = getattr(
|
302
|
-
choice, "message", choice
|
303
|
-
) # Support both OpenAI and instructor
|
317
|
+
message = getattr(choice, "message", choice)
|
304
318
|
|
305
319
|
# If the model wants to call a function/tool
|
306
320
|
if hasattr(message, "function_call") and message.function_call:
|
@@ -316,7 +330,6 @@ class AgentService(AgentServiceInterface):
|
|
316
330
|
)
|
317
331
|
|
318
332
|
# Add the tool result to the prompt for the next round
|
319
|
-
# (You may want to format this differently for your use case)
|
320
333
|
full_prompt += (
|
321
334
|
f"\n\nTool '{function_name}' was called with arguments {arguments}.\n"
|
322
335
|
f"Result: {tool_result}\n"
|
@@ -381,6 +394,7 @@ class AgentService(AgentServiceInterface):
|
|
381
394
|
|
382
395
|
if not text:
|
383
396
|
return ""
|
397
|
+
text = text.replace("’", "'").replace("‘", "'")
|
384
398
|
text = re.sub(r"\[([^\]]+)\]\([^\)]+\)", r"\1", text)
|
385
399
|
text = re.sub(r"`([^`]+)`", r"\1", text)
|
386
400
|
text = re.sub(r"(\*\*|__)(.*?)\1", r"\2", text)
|
@@ -411,9 +425,7 @@ class AgentService(AgentServiceInterface):
|
|
411
425
|
flags=re.UNICODE,
|
412
426
|
)
|
413
427
|
text = emoji_pattern.sub(r" ", text)
|
414
|
-
text = re.sub(
|
415
|
-
r"[^\w\s\.\,\;\:\?\!\'\"\-\(\)]", " ", text
|
416
|
-
) # Keep basic punctuation
|
428
|
+
text = re.sub(r"[^\w\s\.\,\;\:\?\!\'\"\-\(\)]", " ", text)
|
417
429
|
text = re.sub(r"\s+", " ", text)
|
418
430
|
return text.strip()
|
419
431
|
|
solana_agent/services/query.py
CHANGED
@@ -7,7 +7,9 @@ clean separation of concerns.
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
import logging
|
10
|
-
from typing import Any, AsyncGenerator, Dict, List, Literal, Optional, Union
|
10
|
+
from typing import Any, AsyncGenerator, Dict, List, Literal, Optional, Type, Union
|
11
|
+
|
12
|
+
from pydantic import BaseModel
|
11
13
|
|
12
14
|
# Interface imports
|
13
15
|
from solana_agent.interfaces.services.query import QueryService as QueryServiceInterface
|
@@ -86,7 +88,8 @@ class QueryService(QueryServiceInterface):
|
|
86
88
|
] = "mp4",
|
87
89
|
prompt: Optional[str] = None,
|
88
90
|
router: Optional[RoutingServiceInterface] = None,
|
89
|
-
|
91
|
+
output_model: Optional[Type[BaseModel]] = None,
|
92
|
+
) -> AsyncGenerator[Union[str, bytes, BaseModel], None]: # pragma: no cover
|
90
93
|
"""Process the user request with appropriate agent and apply input guardrails.
|
91
94
|
|
92
95
|
Args:
|
@@ -100,6 +103,7 @@ class QueryService(QueryServiceInterface):
|
|
100
103
|
audio_input_format: Audio input format
|
101
104
|
prompt: Optional prompt for the agent
|
102
105
|
router: Optional routing service for processing
|
106
|
+
output_model: Optional Pydantic model for structured output
|
103
107
|
|
104
108
|
Yields:
|
105
109
|
Response chunks (text strings or audio bytes)
|
@@ -267,9 +271,11 @@ class QueryService(QueryServiceInterface):
|
|
267
271
|
memory_context=combined_context,
|
268
272
|
output_format="text",
|
269
273
|
prompt=prompt,
|
274
|
+
output_model=output_model,
|
270
275
|
):
|
271
276
|
yield chunk
|
272
|
-
|
277
|
+
if output_model is None:
|
278
|
+
full_text_response += chunk
|
273
279
|
|
274
280
|
# Store conversation using processed user_text
|
275
281
|
# Note: Storing images in history is not directly supported by current memory provider interface
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: solana-agent
|
3
|
-
Version: 29.
|
3
|
+
Version: 29.3.0
|
4
4
|
Summary: AI Agents for Solana
|
5
5
|
License: MIT
|
6
6
|
Keywords: solana,solana ai,solana agent,ai,ai agent,ai agents
|
@@ -15,12 +15,12 @@ Classifier: Programming Language :: Python :: 3.12
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.13
|
16
16
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
17
17
|
Requires-Dist: instructor (==1.8.3)
|
18
|
-
Requires-Dist: llama-index-core (==0.12.
|
18
|
+
Requires-Dist: llama-index-core (==0.12.39)
|
19
19
|
Requires-Dist: llama-index-embeddings-openai (==0.3.1)
|
20
20
|
Requires-Dist: logfire (==3.16.1)
|
21
|
-
Requires-Dist: openai (==1.82.
|
21
|
+
Requires-Dist: openai (==1.82.1)
|
22
22
|
Requires-Dist: pillow (==11.2.1)
|
23
|
-
Requires-Dist: pinecone (==7.0.
|
23
|
+
Requires-Dist: pinecone (==7.0.2)
|
24
24
|
Requires-Dist: pydantic (>=2)
|
25
25
|
Requires-Dist: pymongo (==4.13.0)
|
26
26
|
Requires-Dist: pypdf (==5.5.0)
|
@@ -64,6 +64,7 @@ Build your AI agents in three lines of code!
|
|
64
64
|
* Extensible Tooling
|
65
65
|
* Automatic Tool Workflows
|
66
66
|
* Autonomous Operation
|
67
|
+
* Structured Outputs
|
67
68
|
* Knowledge Base
|
68
69
|
* MCP Support
|
69
70
|
* Guardrails
|
@@ -79,7 +80,7 @@ Build your AI agents in three lines of code!
|
|
79
80
|
* Simple agent definition using JSON
|
80
81
|
* Fast AI responses
|
81
82
|
* Multi-vendor support including OpenAI, Grok, and Gemini AI services
|
82
|
-
* Solana Integration
|
83
|
+
* Solana Integration
|
83
84
|
* MCP tool usage with first-class support for [Zapier](https://zapier.com/mcp)
|
84
85
|
* Integrated observability and tracing via [Pydantic Logfire](https://pydantic.dev/logfire)
|
85
86
|
* Designed for a multi-agent swarm
|
@@ -95,6 +96,7 @@ Build your AI agents in three lines of code!
|
|
95
96
|
* Input and output guardrails for content filtering, safety, and data sanitization
|
96
97
|
* Generate custom images based on text prompts with storage on S3 compatible services
|
97
98
|
* Automatic sequential tool workflows allowing agents to chain multiple tools
|
99
|
+
* Deterministically return structured outputs
|
98
100
|
* Combine with event-driven systems to create autonomous agents
|
99
101
|
|
100
102
|
## Stack
|
@@ -341,6 +343,38 @@ async for response in solana_agent.process("user123", "What is in this image? De
|
|
341
343
|
print(response, end="")
|
342
344
|
```
|
343
345
|
|
346
|
+
### Structured Outputs
|
347
|
+
|
348
|
+
```python
|
349
|
+
from solana_agent import SolanaAgent
|
350
|
+
|
351
|
+
config = {
|
352
|
+
"openai": {
|
353
|
+
"api_key": "your-openai-api-key",
|
354
|
+
},
|
355
|
+
"agents": [
|
356
|
+
{
|
357
|
+
"name": "researcher",
|
358
|
+
"instructions": "You are a research expert.",
|
359
|
+
"specialization": "Researcher",
|
360
|
+
}
|
361
|
+
],
|
362
|
+
}
|
363
|
+
|
364
|
+
solana_agent = SolanaAgent(config=config)
|
365
|
+
|
366
|
+
class ResearchProposal(BaseModel):
|
367
|
+
title: str
|
368
|
+
abstract: str
|
369
|
+
key_points: list[str]
|
370
|
+
|
371
|
+
full_response = None
|
372
|
+
async for response in solana_agent.process("user123", "Research the life of Ben Franklin - the founding Father.", output_model=ResearchProposal):
|
373
|
+
full_response = response
|
374
|
+
|
375
|
+
print(full_response.model_dump())
|
376
|
+
```
|
377
|
+
|
344
378
|
### Command Line Interface (CLI)
|
345
379
|
|
346
380
|
Solana Agent includes a command-line interface (CLI) for text-based chat using a configuration file.
|
@@ -575,6 +609,8 @@ async for response in solana_agent.process("user123", "Summarize the annual repo
|
|
575
609
|
|
576
610
|
Guardrails allow you to process and potentially modify user input before it reaches the agent (Input Guardrails) and agent output before it's sent back to the user (Output Guardrails). This is useful for implementing safety checks, content moderation, data sanitization, or custom transformations.
|
577
611
|
|
612
|
+
Guardrails don't work with structured outputs.
|
613
|
+
|
578
614
|
Solana Agent provides a built-in PII scrubber based on [scrubadub](https://github.com/LeapBeyond/scrubadub).
|
579
615
|
|
580
616
|
```python
|
@@ -615,6 +651,8 @@ config = {
|
|
615
651
|
|
616
652
|
#### Example Custom Guardrails
|
617
653
|
|
654
|
+
Guardrails don't work with structured outputs.
|
655
|
+
|
618
656
|
```python
|
619
657
|
from solana_agent import InputGuardrail, OutputGuardrail
|
620
658
|
import logging
|
@@ -655,212 +693,12 @@ Tools empower agents to interact with external systems, fetch data, or perform a
|
|
655
693
|
|
656
694
|
Tools can be used from plugins like Solana Agent Kit (sakit) or via inline tools. Tools available via plugins integrate automatically with Solana Agent.
|
657
695
|
|
658
|
-
### Solana
|
659
|
-
|
660
|
-
This plugin enables Solana Agent to transfer SOL and SPL tokens from the agent's wallet to the destination wallet.
|
661
|
-
|
662
|
-
Don't use tickers - but mint addresses in your user queries.
|
663
|
-
|
664
|
-
`pip install sakit`
|
665
|
-
|
666
|
-
```python
|
667
|
-
config = {
|
668
|
-
"tools": {
|
669
|
-
"solana_transfer": {
|
670
|
-
"rpc_url": "my-rpc-url", # Required - your RPC URL - Helius is recommended
|
671
|
-
"private_key": "my-private-key", # Required - base58 string - please use env vars to store the key as it is very confidential
|
672
|
-
},
|
673
|
-
},
|
674
|
-
"agents": [
|
675
|
-
{
|
676
|
-
"name": "solana_expert",
|
677
|
-
"instructions": "You are a Solana expert that can transfer tokens.",
|
678
|
-
"specialization": "Solana Blockchain",
|
679
|
-
"tools": ["solana_transfer"], # Enable the tool for this agent
|
680
|
-
}
|
681
|
-
],
|
682
|
-
}
|
683
|
-
|
684
|
-
solana_agent = SolanaAgent(config=config)
|
685
|
-
|
686
|
-
async for response in solana_agent.process("user123", "Transfer 0.01 Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB to DzvqBkUHUhuhHtNKGWSCVEAm2rHdm9bxxdQYC6mZBZyF"):
|
687
|
-
print(response, end="")
|
688
|
-
```
|
689
|
-
|
690
|
-
### Solana Swap
|
691
|
-
|
692
|
-
This plugin enables Solana Agent to trade (swap) tokens using Jupiter.
|
693
|
-
|
694
|
-
Don't use tickers - but mint addresses in your user queries.
|
695
|
-
|
696
|
-
`pip install sakit`
|
697
|
-
|
698
|
-
```python
|
699
|
-
config = {
|
700
|
-
"tools": {
|
701
|
-
"solana_swap": {
|
702
|
-
"rpc_url": "my-rpc-url", # Required - your RPC URL - Helius is recommended
|
703
|
-
"private_key": "my-private-key", # Required - base58 string - please use env vars to store the key as it is very confidential
|
704
|
-
"jupiter_url": "my-custom-url" # Optional - if you are using a custom Jupiter service like Metis from QuickNode
|
705
|
-
},
|
706
|
-
},
|
707
|
-
"agents": [
|
708
|
-
{
|
709
|
-
"name": "solana_expert",
|
710
|
-
"instructions": "You are a Solana expert that can swap tokens.",
|
711
|
-
"specialization": "Solana Blockchain",
|
712
|
-
"tools": ["solana_swap"], # Enable the tool for this agent
|
713
|
-
}
|
714
|
-
],
|
715
|
-
}
|
716
|
-
|
717
|
-
solana_agent = SolanaAgent(config=config)
|
718
|
-
|
719
|
-
async for response in solana_agent.process("user123", "Swap 0.01 Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB to So11111111111111111111111111111111111111112"):
|
720
|
-
print(response, end="")
|
721
|
-
```
|
722
|
-
|
723
|
-
### Internet Search
|
724
|
-
|
725
|
-
`pip install sakit`
|
726
|
-
|
727
|
-
```python
|
728
|
-
from solana_agent import SolanaAgent
|
696
|
+
### Solana Agent Kit
|
729
697
|
|
730
|
-
|
731
|
-
"openai": {
|
732
|
-
"api_key": "your-openai-api-key",
|
733
|
-
},
|
734
|
-
"tools": {
|
735
|
-
"search_internet": {
|
736
|
-
"api_key": "your-openai-api-key",
|
737
|
-
},
|
738
|
-
},
|
739
|
-
"agents": [
|
740
|
-
{
|
741
|
-
"name": "news_specialist",
|
742
|
-
"instructions": "You are an expert news agent. You use your search_internet tool to get the latest information.",
|
743
|
-
"specialization": "News researcher and specialist",
|
744
|
-
"tools": ["search_internet"], # Enable the tool for this agent
|
745
|
-
}
|
746
|
-
],
|
747
|
-
}
|
748
|
-
|
749
|
-
solana_agent = SolanaAgent(config=config)
|
750
|
-
|
751
|
-
async for response in solana_agent.process("user123", "What is the latest news on Elon Musk?"):
|
752
|
-
print(response, end="")
|
753
|
-
```
|
754
|
-
|
755
|
-
### MCP
|
756
|
-
|
757
|
-
[Zapier](https://zapier.com/mcp) MCP has been tested, works, and is supported.
|
758
|
-
|
759
|
-
Zapier integrates over 7,000+ apps with 30,000+ actions that your Solana Agent can utilize.
|
760
|
-
|
761
|
-
Other MCP servers may work but are not supported.
|
762
|
-
|
763
|
-
`pip install sakit`
|
764
|
-
|
765
|
-
```python
|
766
|
-
from solana_agent import SolanaAgent
|
767
|
-
|
768
|
-
config = {
|
769
|
-
"tools": {
|
770
|
-
"mcp": {
|
771
|
-
"url": "my-zapier-mcp-url",
|
772
|
-
}
|
773
|
-
},
|
774
|
-
"agents": [
|
775
|
-
{
|
776
|
-
"name": "zapier_expert",
|
777
|
-
"instructions": "You are an expert in using Zapier integrations using MCP. You always use the mcp tool to perform Zapier AI like actions.",
|
778
|
-
"specialization": "Zapier service integration expert",
|
779
|
-
"tools": ["mcp"], # Enable the tool for this agent
|
780
|
-
}
|
781
|
-
]
|
782
|
-
}
|
783
|
-
|
784
|
-
solana_agent = SolanaAgent(config=config)
|
785
|
-
|
786
|
-
async for response in solana_agent.process("user123", "Send an email to bob@bob.com to clean his room!"):
|
787
|
-
print(response, end="")
|
788
|
-
```
|
789
|
-
|
790
|
-
### Image Generation
|
791
|
-
|
792
|
-
Generate images using OpenAI, Grok, or Gemini image models and upload them to S3-compatible storage.
|
793
|
-
|
794
|
-
`pip install sakit`
|
795
|
-
|
796
|
-
```python
|
797
|
-
from solana_agent import SolanaAgent
|
798
|
-
|
799
|
-
config = {
|
800
|
-
"tools": {
|
801
|
-
"image_gen": {
|
802
|
-
"provider": "openai", # Required: either "openai", "grok", or "gemini"
|
803
|
-
"api_key": "your-api-key", # Required: your OpenAI or Grok or Gemini API key
|
804
|
-
"s3_endpoint_url": "https://your-s3-endpoint.com", # Required: e.g., https://nyc3.digitaloceanspaces.com
|
805
|
-
"s3_access_key_id": "YOUR_S3_ACCESS_KEY", # Required: Your S3 access key ID
|
806
|
-
"s3_secret_access_key": "YOUR_S3_SECRET_KEY", # Required: Your S3 secret access key
|
807
|
-
"s3_bucket_name": "your-bucket-name", # Required: The name of your S3 bucket
|
808
|
-
"s3_region_name": "your-region", # Optional: e.g., "nyc3", needed by some providers
|
809
|
-
"s3_public_url_base": "https://your-cdn-or-bucket-url.com/", # Optional: Custom base URL for public links (include trailing slash). If omitted, a standard URL is constructed.
|
810
|
-
}
|
811
|
-
},
|
812
|
-
"agents": [
|
813
|
-
{
|
814
|
-
"name": "image_creator",
|
815
|
-
"instructions": "You are a creative assistant that generates images based on user descriptions. Use the image_gen tool to create and store the image.",
|
816
|
-
"specialization": "Image generation and storage",
|
817
|
-
"tools": ["image_gen"], # Enable the tool for this agent
|
818
|
-
}
|
819
|
-
]
|
820
|
-
}
|
821
|
-
|
822
|
-
solana_agent = SolanaAgent(config=config)
|
823
|
-
|
824
|
-
async for response in solana_agent.process("user123", "Generate an image of a smiling unicorn!"):
|
825
|
-
print(response, end="")
|
826
|
-
```
|
827
|
-
|
828
|
-
### Nemo Agent
|
829
|
-
|
830
|
-
This plugin allows the agent to generate python programs using [Nemo Agent](https://nemo-agent.com) and uploads the files in a ZIP file to s3-compatible storage. It returns the public URL of the zip file.
|
831
|
-
|
832
|
-
This has been tested using [Cloudflare R2](https://developers.cloudflare.com/r2/).
|
833
|
-
|
834
|
-
```python
|
835
|
-
from solana_agent import SolanaAgent
|
836
|
-
|
837
|
-
config = {
|
838
|
-
"tools": {
|
839
|
-
"nemo_agent": {
|
840
|
-
"provider": "openai", # Required: either "openai" or "gemini"
|
841
|
-
"api_key": "your-api-key", # Required: your OpenAI or Gemini API key
|
842
|
-
"s3_endpoint_url": "https://your-s3-endpoint.com", # Required: e.g., https://nyc3.digitaloceanspaces.com
|
843
|
-
"s3_access_key_id": "YOUR_S3_ACCESS_KEY", # Required: Your S3 access key ID
|
844
|
-
"s3_secret_access_key": "YOUR_S3_SECRET_KEY", # Required: Your S3 secret access key
|
845
|
-
"s3_bucket_name": "your-bucket-name", # Required: The name of your S3 bucket
|
846
|
-
"s3_region_name": "your-region", # Optional: e.g., "nyc3", needed by some providers
|
847
|
-
"s3_public_url_base": "https://your-cdn-or-bucket-url.com/", # Optional: Custom base URL for public links (include trailing slash). If omitted, a standard URL is constructed.
|
848
|
-
}
|
849
|
-
},
|
850
|
-
"agents": [
|
851
|
-
{
|
852
|
-
"name": "python_dev",
|
853
|
-
"instructions": "You are an expert Python Developer. You always use your nemo_agent tool to generate python code.",
|
854
|
-
"specialization": "Python Developer",
|
855
|
-
"tools": ["nemo_agent"], # Enable the tool for this agent
|
856
|
-
}
|
857
|
-
]
|
858
|
-
}
|
859
|
-
|
860
|
-
solana_agent = SolanaAgent(config=config)
|
698
|
+
[Solana Agent Kit](https://github.com/truemagic-coder/solana-agent-kit)
|
861
699
|
|
862
|
-
|
863
|
-
|
700
|
+
```bash
|
701
|
+
pip install sakit
|
864
702
|
```
|
865
703
|
|
866
704
|
### Inline Tool Example
|
@@ -1,11 +1,11 @@
|
|
1
1
|
solana_agent/__init__.py,sha256=g83qhMOCwcWL19V4CYbQwl0Ykpb0xn49OUh05i-pu3g,1001
|
2
2
|
solana_agent/adapters/__init__.py,sha256=tiEEuuy0NF3ngc_tGEcRTt71zVI58v3dYY9RvMrF2Cg,204
|
3
3
|
solana_agent/adapters/mongodb_adapter.py,sha256=Hq3S8VzfLmnPjV40z8yJXGqUamOJcX5GbOMd-1nNWO4,3175
|
4
|
-
solana_agent/adapters/openai_adapter.py,sha256=
|
4
|
+
solana_agent/adapters/openai_adapter.py,sha256=2-YvMbrBdrHCkMt1qJPD6B926vgfEdkHqnbu3exUe9c,23584
|
5
5
|
solana_agent/adapters/pinecone_adapter.py,sha256=XlfOpoKHwzpaU4KZnovO2TnEYbsw-3B53ZKQDtBeDgU,23847
|
6
6
|
solana_agent/cli.py,sha256=FGvTIQmKLp6XsQdyKtuhIIfbBtMmcCCXfigNrj4bzMc,4704
|
7
7
|
solana_agent/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
-
solana_agent/client/solana_agent.py,sha256=
|
8
|
+
solana_agent/client/solana_agent.py,sha256=ZNBRpougMi8xjkFQffSyrkJCnbRe7C2rKOjJfhQN5ug,9191
|
9
9
|
solana_agent/domains/__init__.py,sha256=HiC94wVPRy-QDJSSRywCRrhrFfTBeHjfi5z-QfZv46U,168
|
10
10
|
solana_agent/domains/agent.py,sha256=3Q1wg4eIul0CPpaYBOjEthKTfcdhf1SAiWc2R-IMGO8,2561
|
11
11
|
solana_agent/domains/routing.py,sha256=1yR4IswGcmREGgbOOI6TKCfuM7gYGOhQjLkBqnZ-rNo,582
|
@@ -13,16 +13,16 @@ solana_agent/factories/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
13
13
|
solana_agent/factories/agent_factory.py,sha256=P8d-wGdWhksu79jngwTtL4jOeMjeo3OfiUJhwPWVh7U,15897
|
14
14
|
solana_agent/guardrails/pii.py,sha256=FCz1IC3mmkr41QFFf5NaC0fwJrVkwFsxgyOCS2POO5I,4428
|
15
15
|
solana_agent/interfaces/__init__.py,sha256=IQs1WIM1FeKP1-kY2FEfyhol_dB-I-VAe2rD6jrVF6k,355
|
16
|
-
solana_agent/interfaces/client/client.py,sha256=
|
16
|
+
solana_agent/interfaces/client/client.py,sha256=9hg35-hp_CI-WVGOXehBE1ZCKYahLmbeAvtQOYmML4o,3245
|
17
17
|
solana_agent/interfaces/guardrails/guardrails.py,sha256=gZCQ1FrirW-mX6s7FoYrbRs6golsp-x269kk4kQiZzc,572
|
18
18
|
solana_agent/interfaces/plugins/plugins.py,sha256=Rz52cWBLdotwf4kV-2mC79tRYlN29zHSu1z9-y1HVPk,3329
|
19
19
|
solana_agent/interfaces/providers/data_storage.py,sha256=Y92Cq8BtC55VlsYLD7bo3ofqQabNnlg7Q4H1Q6CDsLU,1713
|
20
|
-
solana_agent/interfaces/providers/llm.py,sha256=
|
20
|
+
solana_agent/interfaces/providers/llm.py,sha256=Si1xvybHKC6bhjTYjGQi5K9PO9WA7Te29oqs24jxRlY,2998
|
21
21
|
solana_agent/interfaces/providers/memory.py,sha256=h3HEOwWCiFGIuFBX49XOv1jFaQW3NGjyKPOfmQloevk,1011
|
22
22
|
solana_agent/interfaces/providers/vector_storage.py,sha256=XPYzvoWrlDVFCS9ItBmoqCFWXXWNYY-d9I7_pvP7YYk,1561
|
23
|
-
solana_agent/interfaces/services/agent.py,sha256=
|
23
|
+
solana_agent/interfaces/services/agent.py,sha256=A-Hmgelr3g_qaNB0PEPMFHxB5nSCBK0WJ5hauJtIcmI,2257
|
24
24
|
solana_agent/interfaces/services/knowledge_base.py,sha256=Mu8lCGFXPmI_IW5LRGti7octLoWZIg4k5PmGwPfe7LQ,1479
|
25
|
-
solana_agent/interfaces/services/query.py,sha256=
|
25
|
+
solana_agent/interfaces/services/query.py,sha256=Co-pThoT4Zz8jhwKt5fV3LH9MaE_lSyEwNFxsMnTU9Y,1737
|
26
26
|
solana_agent/interfaces/services/routing.py,sha256=Qbn3-DQGVSQKaegHDekSFmn_XCklA0H2f0XUx9-o3wA,367
|
27
27
|
solana_agent/plugins/__init__.py,sha256=coZdgJKq1ExOaj6qB810i3rEhbjdVlrkN76ozt_Ojgo,193
|
28
28
|
solana_agent/plugins/manager.py,sha256=mO_dKSVJ8GToD3wZflMcpKDEBXRoaaMRtY267HENCI0,5542
|
@@ -32,12 +32,12 @@ solana_agent/plugins/tools/auto_tool.py,sha256=uihijtlc9CCqCIaRcwPuuN7o1SHIpWL2G
|
|
32
32
|
solana_agent/repositories/__init__.py,sha256=fP83w83CGzXLnSdq-C5wbw9EhWTYtqE2lQTgp46-X_4,163
|
33
33
|
solana_agent/repositories/memory.py,sha256=SKQJJisrERccqd4cm4ERlp5BmKHVQAp1fzp8ce4i2bw,8377
|
34
34
|
solana_agent/services/__init__.py,sha256=iko0c2MlF8b_SA_nuBGFllr2E3g_JowOrOzGcnU9tkA,162
|
35
|
-
solana_agent/services/agent.py,sha256=
|
35
|
+
solana_agent/services/agent.py,sha256=kznv2Jhpc4DiFbB-kV3eG5FuPPgl2Hu26h5yCsxyCuw,18624
|
36
36
|
solana_agent/services/knowledge_base.py,sha256=ZvOPrSmcNDgUzz4bJIQ4LeRl9vMZiK9hOfs71IpB7Bk,32735
|
37
|
-
solana_agent/services/query.py,sha256=
|
37
|
+
solana_agent/services/query.py,sha256=3v5Ym8UqL0rfOC-0MWHALAsS2jVWdpUR3A-YI9n0xyo,18771
|
38
38
|
solana_agent/services/routing.py,sha256=C5Ku4t9TqvY7S8wlUPMTC04HCrT4Ib3E8Q8yX0lVU_s,7137
|
39
|
-
solana_agent-29.
|
40
|
-
solana_agent-29.
|
41
|
-
solana_agent-29.
|
42
|
-
solana_agent-29.
|
43
|
-
solana_agent-29.
|
39
|
+
solana_agent-29.3.0.dist-info/LICENSE,sha256=BnSRc-NSFuyF2s496l_4EyrwAP6YimvxWcjPiJ0J7g4,1057
|
40
|
+
solana_agent-29.3.0.dist-info/METADATA,sha256=YYGG6n8-S23KwMjDY3Rmec7DcCHaVTv8e4lecOB9J7I,29849
|
41
|
+
solana_agent-29.3.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
42
|
+
solana_agent-29.3.0.dist-info/entry_points.txt,sha256=-AuT_mfqk8dlZ0pHuAjx1ouAWpTRjpqvEUa6YV3lmc0,53
|
43
|
+
solana_agent-29.3.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|