solana-agent 27.4.3__tar.gz → 28.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.
- {solana_agent-27.4.3 → solana_agent-28.0.0}/PKG-INFO +108 -52
- {solana_agent-27.4.3 → solana_agent-28.0.0}/README.md +106 -51
- {solana_agent-27.4.3 → solana_agent-28.0.0}/pyproject.toml +2 -1
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/__init__.py +7 -2
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/adapters/openai_adapter.py +17 -21
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/factories/agent_factory.py +60 -79
- solana_agent-28.0.0/solana_agent/guardrails/pii.py +107 -0
- solana_agent-28.0.0/solana_agent/interfaces/guardrails/guardrails.py +26 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/interfaces/providers/llm.py +1 -1
- solana_agent-28.0.0/solana_agent/services/agent.py +952 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/services/query.py +140 -58
- solana_agent-27.4.3/solana_agent/services/agent.py +0 -683
- {solana_agent-27.4.3 → solana_agent-28.0.0}/LICENSE +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/adapters/__init__.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/adapters/mongodb_adapter.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/adapters/pinecone_adapter.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/client/__init__.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/client/solana_agent.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/domains/__init__.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/domains/agent.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/domains/routing.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/factories/__init__.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/interfaces/__init__.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/interfaces/client/client.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/interfaces/plugins/plugins.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/interfaces/providers/data_storage.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/interfaces/providers/memory.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/interfaces/providers/vector_storage.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/interfaces/services/agent.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/interfaces/services/knowledge_base.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/interfaces/services/query.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/interfaces/services/routing.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/plugins/__init__.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/plugins/manager.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/plugins/registry.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/plugins/tools/__init__.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/plugins/tools/auto_tool.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/repositories/__init__.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/repositories/memory.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/services/__init__.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/services/knowledge_base.py +0 -0
- {solana_agent-27.4.3 → solana_agent-28.0.0}/solana_agent/services/routing.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: solana-agent
|
3
|
-
Version:
|
3
|
+
Version: 28.0.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
|
@@ -22,6 +22,7 @@ Requires-Dist: pinecone (>=6.0.2,<7.0.0)
|
|
22
22
|
Requires-Dist: pydantic (>=2)
|
23
23
|
Requires-Dist: pymongo (>=4.12.0,<5.0.0)
|
24
24
|
Requires-Dist: pypdf (>=5.4.0,<6.0.0)
|
25
|
+
Requires-Dist: scrubadub (>=2.0.1,<3.0.0)
|
25
26
|
Requires-Dist: zep-cloud (>=2.10.1,<3.0.0)
|
26
27
|
Project-URL: Documentation, https://docs.solana-agent.com
|
27
28
|
Project-URL: Homepage, https://solana-agent.com
|
@@ -58,11 +59,13 @@ Build your AI agents in three lines of code!
|
|
58
59
|
* Intelligent Routing
|
59
60
|
* Business Alignment
|
60
61
|
* Extensible Tooling
|
62
|
+
* Automatic Tool Workflows
|
61
63
|
* Knowledge Base
|
62
64
|
* MCP Support
|
65
|
+
* Guardrails
|
63
66
|
* Tested & Secure
|
64
67
|
* Built in Python
|
65
|
-
* Powers [CometHeart](https://cometheart.com)
|
68
|
+
* Powers [CometHeart](https://cometheart.com)
|
66
69
|
|
67
70
|
## Features
|
68
71
|
|
@@ -81,26 +84,26 @@ Build your AI agents in three lines of code!
|
|
81
84
|
* Powerful tool integration using standard Python packages and/or inline tools
|
82
85
|
* Assigned tools are utilized by agents automatically and effectively
|
83
86
|
* Integrated Knowledge Base with semantic search and automatic PDF chunking
|
87
|
+
* Input and output guardrails for content filtering, safety, and data sanitization
|
88
|
+
* Automatic sequential tool workflows allowing agents to chain multiple tools
|
84
89
|
|
85
90
|
## Stack
|
86
91
|
|
87
92
|
### Tech
|
88
93
|
|
89
94
|
* [Python](https://python.org) - Programming Language
|
90
|
-
* [OpenAI](https://openai.com)
|
95
|
+
* [OpenAI](https://openai.com) - AI Provider
|
91
96
|
* [MongoDB](https://mongodb.com) - Conversational History (optional)
|
92
97
|
* [Zep Cloud](https://getzep.com) - Conversational Memory (optional)
|
93
98
|
* [Pinecone](https://pinecone.io) - Knowledge Base (optional)
|
94
99
|
|
95
|
-
###
|
100
|
+
### AI Models Used
|
96
101
|
|
97
|
-
* [gpt-4.1
|
102
|
+
* [gpt-4.1](https://platform.openai.com/docs/models/gpt-4.1) (agent)
|
98
103
|
* [gpt-4.1-nano](https://platform.openai.com/docs/models/gpt-4.1-nano) (router)
|
99
104
|
* [text-embedding-3-large](https://platform.openai.com/docs/models/text-embedding-3-large) or [text-embedding-3-small](https://platform.openai.com/docs/models/text-embedding-3-small) (embedding)
|
100
105
|
* [tts-1](https://platform.openai.com/docs/models/tts-1) (audio TTS)
|
101
106
|
* [gpt-4o-mini-transcribe](https://platform.openai.com/docs/models/gpt-4o-mini-transcribe) (audio transcription)
|
102
|
-
* [gemini-2.5-flash-preview](https://ai.google.dev/gemini-api/docs/models#gemini-2.5-flash-preview) (optional)
|
103
|
-
* [grok-3-mini-fast-beta](https://docs.x.ai/docs/models#models-and-pricing) (optional)
|
104
107
|
|
105
108
|
## Installation
|
106
109
|
|
@@ -110,13 +113,13 @@ You can install Solana Agent using pip:
|
|
110
113
|
|
111
114
|
## Flows
|
112
115
|
|
113
|
-
In both flows of single and multiple agents - it is one user query to one agent using one
|
116
|
+
In both flows of single and multiple agents - it is one user query to one agent using one or many tools (if needed).
|
114
117
|
|
115
|
-
An agent can have multiple tools and will choose the best
|
118
|
+
An agent can have multiple tools and will choose the best ones to fulfill the user's query.
|
116
119
|
|
117
|
-
Routing is determined by optimal domain expertise of the agent for the user query.
|
120
|
+
Routing is determined by optimal domain expertise of the agent for the user's query.
|
118
121
|
|
119
|
-
When the agent uses
|
122
|
+
When the agent uses tools it feeds the tools output back to itself to generate the final response.
|
120
123
|
|
121
124
|
This is important as tools generally output unstructured and unformatted data that the agent needs to prepare for the user.
|
122
125
|
|
@@ -125,13 +128,13 @@ Keep this in mind while designing your agentic systems using Solana Agent.
|
|
125
128
|
```ascii
|
126
129
|
Single Agent
|
127
130
|
|
128
|
-
┌────────┐ ┌─────────┐
|
129
|
-
│ │ │ │ │
|
130
|
-
│ │ │ │ │
|
131
|
-
│ User │◄──────►│ Agent │◄──────►│
|
132
|
-
│ │ │ │ │
|
133
|
-
│ │ │ │ │
|
134
|
-
└────────┘ └─────────┘
|
131
|
+
┌────────┐ ┌─────────┐ ┌────────-┐
|
132
|
+
│ │ │ │ │ │
|
133
|
+
│ │ │ │ │ │
|
134
|
+
│ User │◄──────►│ Agent │◄──────►│ Tools │
|
135
|
+
│ │ │ │ │ │
|
136
|
+
│ │ │ │ │ │
|
137
|
+
└────────┘ └─────────┘ └────────-┘
|
135
138
|
|
136
139
|
|
137
140
|
|
@@ -139,13 +142,13 @@ Keep this in mind while designing your agentic systems using Solana Agent.
|
|
139
142
|
|
140
143
|
Multiple Agents
|
141
144
|
|
142
|
-
┌────────┐ ┌──────────┐ ┌─────────┐
|
143
|
-
│ │ │ │ │ │ │
|
144
|
-
│ │ │ │ │ │ │
|
145
|
-
┌───►│ User ├───────►│ Router ├───────►│ Agent │◄──────►│
|
146
|
-
│ │ │ │ │ │ │ │
|
147
|
-
│ │ │ │ │ │ │ │
|
148
|
-
│ └────────┘ └──────────┘ └────┬────┘
|
145
|
+
┌────────┐ ┌──────────┐ ┌─────────┐ ┌────────-┐
|
146
|
+
│ │ │ │ │ │ │ │
|
147
|
+
│ │ │ │ │ │ │ │
|
148
|
+
┌───►│ User ├───────►│ Router ├───────►│ Agent │◄──────►│ Tools │
|
149
|
+
│ │ │ │ │ │ │ │ │
|
150
|
+
│ │ │ │ │ │ │ │ │
|
151
|
+
│ └────────┘ └──────────┘ └────┬────┘ └────────-┘
|
149
152
|
│ │
|
150
153
|
│ │
|
151
154
|
│ │
|
@@ -316,30 +319,6 @@ config = {
|
|
316
319
|
}
|
317
320
|
```
|
318
321
|
|
319
|
-
### Gemini
|
320
|
-
|
321
|
-
This allows Gemini to replace OpenAI for agent and router.
|
322
|
-
|
323
|
-
```python
|
324
|
-
config = {
|
325
|
-
"gemini": {
|
326
|
-
"api_key": "your-gemini-api-key",
|
327
|
-
},
|
328
|
-
}
|
329
|
-
```
|
330
|
-
|
331
|
-
### Grok
|
332
|
-
|
333
|
-
This allows Grok to replace OpenAI (or Gemini) for agent.
|
334
|
-
|
335
|
-
```python
|
336
|
-
config = {
|
337
|
-
"grok": {
|
338
|
-
"api_key": "your-grok-api-key",
|
339
|
-
},
|
340
|
-
}
|
341
|
-
```
|
342
|
-
|
343
322
|
### Knowledge Base
|
344
323
|
|
345
324
|
The Knowledge Base (KB) is meant to store text values and/or small PDFs.
|
@@ -448,12 +427,90 @@ async for response in solana_agent.process("user123", "Summarize the annual repo
|
|
448
427
|
print(response, end="")
|
449
428
|
```
|
450
429
|
|
430
|
+
### Guardrails
|
431
|
+
|
432
|
+
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.
|
433
|
+
|
434
|
+
Solana Agent provides a built-in PII scrubber based on [scrubadub](https://github.com/LeapBeyond/scrubadub).
|
435
|
+
|
436
|
+
```python
|
437
|
+
from solana_agent import SolanaAgent
|
438
|
+
|
439
|
+
config = {
|
440
|
+
"guardrails": {
|
441
|
+
"input": [
|
442
|
+
# Example using a custom input guardrail
|
443
|
+
{
|
444
|
+
"class": "MyInputGuardrail",
|
445
|
+
"config": {"setting1": "value1"}
|
446
|
+
},
|
447
|
+
# Example using the built-in PII guardrail for input
|
448
|
+
{
|
449
|
+
"class": "solana_agent.guardrails.pii.PII",
|
450
|
+
"config": {
|
451
|
+
"locale": "en_GB", # Optional: Specify locale (default: en_US)
|
452
|
+
"replacement": "[REDACTED]" # Optional: Custom replacement format
|
453
|
+
}
|
454
|
+
}
|
455
|
+
],
|
456
|
+
"output": [
|
457
|
+
# Example using a custom output guardrail
|
458
|
+
{
|
459
|
+
"class": "MyOutputGuardrail",
|
460
|
+
"config": {"filter_level": "high"}
|
461
|
+
},
|
462
|
+
# Example using the built-in PII guardrail for output (with defaults)
|
463
|
+
{
|
464
|
+
"class": "solana_agent.guardrails.pii.PII"
|
465
|
+
# No config needed to use defaults
|
466
|
+
}
|
467
|
+
]
|
468
|
+
},
|
469
|
+
}
|
470
|
+
```
|
471
|
+
|
472
|
+
#### Example Custom Guardrails
|
473
|
+
|
474
|
+
```python
|
475
|
+
from solana_agent import InputGuardrail, OutputGuardrail
|
476
|
+
import logging
|
477
|
+
|
478
|
+
logger = logging.getLogger(__name__)
|
479
|
+
|
480
|
+
class MyInputGuardrail(InputGuardrail):
|
481
|
+
def __init__(self, config=None):
|
482
|
+
super().__init__(config)
|
483
|
+
self.setting1 = self.config.get("setting1", "default_value")
|
484
|
+
logger.info(f"MyInputGuardrail initialized with setting1: {self.setting1}")
|
485
|
+
|
486
|
+
async def process(self, text: str) -> str:
|
487
|
+
# Example: Convert input to lowercase
|
488
|
+
processed_text = text.lower()
|
489
|
+
logger.debug(f"Input Guardrail processed: {text} -> {processed_text}")
|
490
|
+
return processed_text
|
491
|
+
|
492
|
+
class MyOutputGuardrail(OutputGuardrail):
|
493
|
+
def __init__(self, config=None):
|
494
|
+
super().__init__(config)
|
495
|
+
self.filter_level = self.config.get("filter_level", "low")
|
496
|
+
logger.info(f"MyOutputGuardrail initialized with filter_level: {self.filter_level}")
|
497
|
+
|
498
|
+
async def process(self, text: str) -> str:
|
499
|
+
# Example: Basic profanity filtering (replace with a real library)
|
500
|
+
if self.filter_level == "high" and "badword" in text:
|
501
|
+
processed_text = text.replace("badword", "*******")
|
502
|
+
logger.warning(f"Output Guardrail filtered content.")
|
503
|
+
return processed_text
|
504
|
+
logger.debug("Output Guardrail passed text through.")
|
505
|
+
return text
|
506
|
+
```
|
507
|
+
|
451
508
|
## Tools
|
452
509
|
|
453
510
|
Tools can be used from plugins like Solana Agent Kit (sakit) or via inline tools. Tools available via plugins integrate automatically with Solana Agent.
|
454
511
|
|
455
|
-
* Agents can
|
456
|
-
* Agents choose the best
|
512
|
+
* Agents can use multiple tools per response and should apply the right sequential order (like send an email to bob@bob.com with the latest news on Solana)
|
513
|
+
* Agents choose the best tools for the job
|
457
514
|
* Solana Agent doesn't use OpenAI function calling (tools) as they don't support async functions
|
458
515
|
* Solana Agent tools are async functions
|
459
516
|
|
@@ -528,7 +585,6 @@ Other MCP servers may work but are not supported.
|
|
528
585
|
`pip install sakit`
|
529
586
|
|
530
587
|
```python
|
531
|
-
|
532
588
|
from solana_agent import SolanaAgent
|
533
589
|
|
534
590
|
config = {
|
@@ -28,11 +28,13 @@ Build your AI agents in three lines of code!
|
|
28
28
|
* Intelligent Routing
|
29
29
|
* Business Alignment
|
30
30
|
* Extensible Tooling
|
31
|
+
* Automatic Tool Workflows
|
31
32
|
* Knowledge Base
|
32
33
|
* MCP Support
|
34
|
+
* Guardrails
|
33
35
|
* Tested & Secure
|
34
36
|
* Built in Python
|
35
|
-
* Powers [CometHeart](https://cometheart.com)
|
37
|
+
* Powers [CometHeart](https://cometheart.com)
|
36
38
|
|
37
39
|
## Features
|
38
40
|
|
@@ -51,26 +53,26 @@ Build your AI agents in three lines of code!
|
|
51
53
|
* Powerful tool integration using standard Python packages and/or inline tools
|
52
54
|
* Assigned tools are utilized by agents automatically and effectively
|
53
55
|
* Integrated Knowledge Base with semantic search and automatic PDF chunking
|
56
|
+
* Input and output guardrails for content filtering, safety, and data sanitization
|
57
|
+
* Automatic sequential tool workflows allowing agents to chain multiple tools
|
54
58
|
|
55
59
|
## Stack
|
56
60
|
|
57
61
|
### Tech
|
58
62
|
|
59
63
|
* [Python](https://python.org) - Programming Language
|
60
|
-
* [OpenAI](https://openai.com)
|
64
|
+
* [OpenAI](https://openai.com) - AI Provider
|
61
65
|
* [MongoDB](https://mongodb.com) - Conversational History (optional)
|
62
66
|
* [Zep Cloud](https://getzep.com) - Conversational Memory (optional)
|
63
67
|
* [Pinecone](https://pinecone.io) - Knowledge Base (optional)
|
64
68
|
|
65
|
-
###
|
69
|
+
### AI Models Used
|
66
70
|
|
67
|
-
* [gpt-4.1
|
71
|
+
* [gpt-4.1](https://platform.openai.com/docs/models/gpt-4.1) (agent)
|
68
72
|
* [gpt-4.1-nano](https://platform.openai.com/docs/models/gpt-4.1-nano) (router)
|
69
73
|
* [text-embedding-3-large](https://platform.openai.com/docs/models/text-embedding-3-large) or [text-embedding-3-small](https://platform.openai.com/docs/models/text-embedding-3-small) (embedding)
|
70
74
|
* [tts-1](https://platform.openai.com/docs/models/tts-1) (audio TTS)
|
71
75
|
* [gpt-4o-mini-transcribe](https://platform.openai.com/docs/models/gpt-4o-mini-transcribe) (audio transcription)
|
72
|
-
* [gemini-2.5-flash-preview](https://ai.google.dev/gemini-api/docs/models#gemini-2.5-flash-preview) (optional)
|
73
|
-
* [grok-3-mini-fast-beta](https://docs.x.ai/docs/models#models-and-pricing) (optional)
|
74
76
|
|
75
77
|
## Installation
|
76
78
|
|
@@ -80,13 +82,13 @@ You can install Solana Agent using pip:
|
|
80
82
|
|
81
83
|
## Flows
|
82
84
|
|
83
|
-
In both flows of single and multiple agents - it is one user query to one agent using one
|
85
|
+
In both flows of single and multiple agents - it is one user query to one agent using one or many tools (if needed).
|
84
86
|
|
85
|
-
An agent can have multiple tools and will choose the best
|
87
|
+
An agent can have multiple tools and will choose the best ones to fulfill the user's query.
|
86
88
|
|
87
|
-
Routing is determined by optimal domain expertise of the agent for the user query.
|
89
|
+
Routing is determined by optimal domain expertise of the agent for the user's query.
|
88
90
|
|
89
|
-
When the agent uses
|
91
|
+
When the agent uses tools it feeds the tools output back to itself to generate the final response.
|
90
92
|
|
91
93
|
This is important as tools generally output unstructured and unformatted data that the agent needs to prepare for the user.
|
92
94
|
|
@@ -95,13 +97,13 @@ Keep this in mind while designing your agentic systems using Solana Agent.
|
|
95
97
|
```ascii
|
96
98
|
Single Agent
|
97
99
|
|
98
|
-
┌────────┐ ┌─────────┐
|
99
|
-
│ │ │ │ │
|
100
|
-
│ │ │ │ │
|
101
|
-
│ User │◄──────►│ Agent │◄──────►│
|
102
|
-
│ │ │ │ │
|
103
|
-
│ │ │ │ │
|
104
|
-
└────────┘ └─────────┘
|
100
|
+
┌────────┐ ┌─────────┐ ┌────────-┐
|
101
|
+
│ │ │ │ │ │
|
102
|
+
│ │ │ │ │ │
|
103
|
+
│ User │◄──────►│ Agent │◄──────►│ Tools │
|
104
|
+
│ │ │ │ │ │
|
105
|
+
│ │ │ │ │ │
|
106
|
+
└────────┘ └─────────┘ └────────-┘
|
105
107
|
|
106
108
|
|
107
109
|
|
@@ -109,13 +111,13 @@ Keep this in mind while designing your agentic systems using Solana Agent.
|
|
109
111
|
|
110
112
|
Multiple Agents
|
111
113
|
|
112
|
-
┌────────┐ ┌──────────┐ ┌─────────┐
|
113
|
-
│ │ │ │ │ │ │
|
114
|
-
│ │ │ │ │ │ │
|
115
|
-
┌───►│ User ├───────►│ Router ├───────►│ Agent │◄──────►│
|
116
|
-
│ │ │ │ │ │ │ │
|
117
|
-
│ │ │ │ │ │ │ │
|
118
|
-
│ └────────┘ └──────────┘ └────┬────┘
|
114
|
+
┌────────┐ ┌──────────┐ ┌─────────┐ ┌────────-┐
|
115
|
+
│ │ │ │ │ │ │ │
|
116
|
+
│ │ │ │ │ │ │ │
|
117
|
+
┌───►│ User ├───────►│ Router ├───────►│ Agent │◄──────►│ Tools │
|
118
|
+
│ │ │ │ │ │ │ │ │
|
119
|
+
│ │ │ │ │ │ │ │ │
|
120
|
+
│ └────────┘ └──────────┘ └────┬────┘ └────────-┘
|
119
121
|
│ │
|
120
122
|
│ │
|
121
123
|
│ │
|
@@ -286,30 +288,6 @@ config = {
|
|
286
288
|
}
|
287
289
|
```
|
288
290
|
|
289
|
-
### Gemini
|
290
|
-
|
291
|
-
This allows Gemini to replace OpenAI for agent and router.
|
292
|
-
|
293
|
-
```python
|
294
|
-
config = {
|
295
|
-
"gemini": {
|
296
|
-
"api_key": "your-gemini-api-key",
|
297
|
-
},
|
298
|
-
}
|
299
|
-
```
|
300
|
-
|
301
|
-
### Grok
|
302
|
-
|
303
|
-
This allows Grok to replace OpenAI (or Gemini) for agent.
|
304
|
-
|
305
|
-
```python
|
306
|
-
config = {
|
307
|
-
"grok": {
|
308
|
-
"api_key": "your-grok-api-key",
|
309
|
-
},
|
310
|
-
}
|
311
|
-
```
|
312
|
-
|
313
291
|
### Knowledge Base
|
314
292
|
|
315
293
|
The Knowledge Base (KB) is meant to store text values and/or small PDFs.
|
@@ -418,12 +396,90 @@ async for response in solana_agent.process("user123", "Summarize the annual repo
|
|
418
396
|
print(response, end="")
|
419
397
|
```
|
420
398
|
|
399
|
+
### Guardrails
|
400
|
+
|
401
|
+
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.
|
402
|
+
|
403
|
+
Solana Agent provides a built-in PII scrubber based on [scrubadub](https://github.com/LeapBeyond/scrubadub).
|
404
|
+
|
405
|
+
```python
|
406
|
+
from solana_agent import SolanaAgent
|
407
|
+
|
408
|
+
config = {
|
409
|
+
"guardrails": {
|
410
|
+
"input": [
|
411
|
+
# Example using a custom input guardrail
|
412
|
+
{
|
413
|
+
"class": "MyInputGuardrail",
|
414
|
+
"config": {"setting1": "value1"}
|
415
|
+
},
|
416
|
+
# Example using the built-in PII guardrail for input
|
417
|
+
{
|
418
|
+
"class": "solana_agent.guardrails.pii.PII",
|
419
|
+
"config": {
|
420
|
+
"locale": "en_GB", # Optional: Specify locale (default: en_US)
|
421
|
+
"replacement": "[REDACTED]" # Optional: Custom replacement format
|
422
|
+
}
|
423
|
+
}
|
424
|
+
],
|
425
|
+
"output": [
|
426
|
+
# Example using a custom output guardrail
|
427
|
+
{
|
428
|
+
"class": "MyOutputGuardrail",
|
429
|
+
"config": {"filter_level": "high"}
|
430
|
+
},
|
431
|
+
# Example using the built-in PII guardrail for output (with defaults)
|
432
|
+
{
|
433
|
+
"class": "solana_agent.guardrails.pii.PII"
|
434
|
+
# No config needed to use defaults
|
435
|
+
}
|
436
|
+
]
|
437
|
+
},
|
438
|
+
}
|
439
|
+
```
|
440
|
+
|
441
|
+
#### Example Custom Guardrails
|
442
|
+
|
443
|
+
```python
|
444
|
+
from solana_agent import InputGuardrail, OutputGuardrail
|
445
|
+
import logging
|
446
|
+
|
447
|
+
logger = logging.getLogger(__name__)
|
448
|
+
|
449
|
+
class MyInputGuardrail(InputGuardrail):
|
450
|
+
def __init__(self, config=None):
|
451
|
+
super().__init__(config)
|
452
|
+
self.setting1 = self.config.get("setting1", "default_value")
|
453
|
+
logger.info(f"MyInputGuardrail initialized with setting1: {self.setting1}")
|
454
|
+
|
455
|
+
async def process(self, text: str) -> str:
|
456
|
+
# Example: Convert input to lowercase
|
457
|
+
processed_text = text.lower()
|
458
|
+
logger.debug(f"Input Guardrail processed: {text} -> {processed_text}")
|
459
|
+
return processed_text
|
460
|
+
|
461
|
+
class MyOutputGuardrail(OutputGuardrail):
|
462
|
+
def __init__(self, config=None):
|
463
|
+
super().__init__(config)
|
464
|
+
self.filter_level = self.config.get("filter_level", "low")
|
465
|
+
logger.info(f"MyOutputGuardrail initialized with filter_level: {self.filter_level}")
|
466
|
+
|
467
|
+
async def process(self, text: str) -> str:
|
468
|
+
# Example: Basic profanity filtering (replace with a real library)
|
469
|
+
if self.filter_level == "high" and "badword" in text:
|
470
|
+
processed_text = text.replace("badword", "*******")
|
471
|
+
logger.warning(f"Output Guardrail filtered content.")
|
472
|
+
return processed_text
|
473
|
+
logger.debug("Output Guardrail passed text through.")
|
474
|
+
return text
|
475
|
+
```
|
476
|
+
|
421
477
|
## Tools
|
422
478
|
|
423
479
|
Tools can be used from plugins like Solana Agent Kit (sakit) or via inline tools. Tools available via plugins integrate automatically with Solana Agent.
|
424
480
|
|
425
|
-
* Agents can
|
426
|
-
* Agents choose the best
|
481
|
+
* Agents can use multiple tools per response and should apply the right sequential order (like send an email to bob@bob.com with the latest news on Solana)
|
482
|
+
* Agents choose the best tools for the job
|
427
483
|
* Solana Agent doesn't use OpenAI function calling (tools) as they don't support async functions
|
428
484
|
* Solana Agent tools are async functions
|
429
485
|
|
@@ -498,7 +554,6 @@ Other MCP servers may work but are not supported.
|
|
498
554
|
`pip install sakit`
|
499
555
|
|
500
556
|
```python
|
501
|
-
|
502
557
|
from solana_agent import SolanaAgent
|
503
558
|
|
504
559
|
config = {
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "solana-agent"
|
3
|
-
version = "
|
3
|
+
version = "28.0.0"
|
4
4
|
description = "AI Agents for Solana"
|
5
5
|
authors = ["Bevan Hunt <bevan@bevanhunt.com>"]
|
6
6
|
license = "MIT"
|
@@ -33,6 +33,7 @@ pinecone = "^6.0.2"
|
|
33
33
|
llama-index-core = "^0.12.30"
|
34
34
|
llama-index-embeddings-openai = "^0.3.1"
|
35
35
|
pypdf = "^5.4.0"
|
36
|
+
scrubadub = "^2.0.1"
|
36
37
|
|
37
38
|
[tool.poetry.group.dev.dependencies]
|
38
39
|
pytest = "^8.3.5"
|
@@ -5,8 +5,6 @@ This package provides a modular framework for building AI agent systems with
|
|
5
5
|
multiple specialized agents, memory management, and conversation routing.
|
6
6
|
"""
|
7
7
|
|
8
|
-
__version__ = "14.0.0" # Update with your actual version
|
9
|
-
|
10
8
|
# Client interface (main entry point)
|
11
9
|
from solana_agent.client.solana_agent import SolanaAgent
|
12
10
|
|
@@ -17,6 +15,10 @@ from solana_agent.factories.agent_factory import SolanaAgentFactory
|
|
17
15
|
from solana_agent.plugins.manager import PluginManager
|
18
16
|
from solana_agent.plugins.registry import ToolRegistry
|
19
17
|
from solana_agent.plugins.tools.auto_tool import AutoTool
|
18
|
+
from solana_agent.interfaces.guardrails.guardrails import (
|
19
|
+
InputGuardrail,
|
20
|
+
OutputGuardrail,
|
21
|
+
)
|
20
22
|
|
21
23
|
# Package metadata
|
22
24
|
__all__ = [
|
@@ -28,4 +30,7 @@ __all__ = [
|
|
28
30
|
"PluginManager",
|
29
31
|
"ToolRegistry",
|
30
32
|
"AutoTool",
|
33
|
+
# Guardrails
|
34
|
+
"InputGuardrail",
|
35
|
+
"OutputGuardrail",
|
31
36
|
]
|
@@ -15,7 +15,7 @@ from solana_agent.interfaces.providers.llm import LLMProvider
|
|
15
15
|
|
16
16
|
T = TypeVar("T", bound=BaseModel)
|
17
17
|
|
18
|
-
DEFAULT_CHAT_MODEL = "gpt-4.1
|
18
|
+
DEFAULT_CHAT_MODEL = "gpt-4.1"
|
19
19
|
DEFAULT_PARSE_MODEL = "gpt-4.1-nano"
|
20
20
|
DEFAULT_EMBEDDING_MODEL = "text-embedding-3-large"
|
21
21
|
DEFAULT_EMBEDDING_DIMENSIONS = 3072
|
@@ -129,45 +129,41 @@ class OpenAIAdapter(LLMProvider):
|
|
129
129
|
api_key: Optional[str] = None,
|
130
130
|
base_url: Optional[str] = None,
|
131
131
|
model: Optional[str] = None,
|
132
|
-
) ->
|
133
|
-
"""Generate text from OpenAI models."""
|
132
|
+
) -> str: # pragma: no cover
|
133
|
+
"""Generate text from OpenAI models as a single string."""
|
134
134
|
messages = []
|
135
|
-
|
136
135
|
if system_prompt:
|
137
136
|
messages.append({"role": "system", "content": system_prompt})
|
138
|
-
|
139
137
|
messages.append({"role": "user", "content": prompt})
|
140
138
|
|
141
|
-
# Prepare request parameters
|
139
|
+
# Prepare request parameters - stream is always False now
|
142
140
|
request_params = {
|
143
141
|
"messages": messages,
|
144
|
-
"stream":
|
145
|
-
"model": self.text_model,
|
142
|
+
"stream": False, # Hardcoded to False
|
143
|
+
"model": model or self.text_model,
|
146
144
|
}
|
147
145
|
|
146
|
+
# Determine client based on provided api_key/base_url
|
148
147
|
if api_key and base_url:
|
149
148
|
client = AsyncOpenAI(api_key=api_key, base_url=base_url)
|
150
149
|
else:
|
151
150
|
client = self.client
|
152
151
|
|
153
|
-
if model:
|
154
|
-
request_params["model"] = model
|
155
|
-
|
156
152
|
try:
|
153
|
+
# Make the non-streaming API call
|
157
154
|
response = await client.chat.completions.create(**request_params)
|
158
155
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
156
|
+
# Handle non-streaming response
|
157
|
+
if response.choices and response.choices[0].message.content:
|
158
|
+
full_text = response.choices[0].message.content
|
159
|
+
return full_text # Return the complete string
|
160
|
+
else:
|
161
|
+
print("Received non-streaming response with no content.")
|
162
|
+
return "" # Return empty string if no content
|
164
163
|
|
165
164
|
except Exception as e:
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
print(traceback.format_exc())
|
170
|
-
yield f"I apologize, but I encountered an error: {str(e)}"
|
165
|
+
# Log the error and return an error message string
|
166
|
+
print(f"Error in generate_text: {e}")
|
171
167
|
|
172
168
|
async def parse_structured_output(
|
173
169
|
self,
|