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.
@@ -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
- # Use instructor's structured generation with function calling
435
- response = await patched_client.chat.completions.create(
436
- model=current_parse_model, # Use the determined model
437
- messages=messages,
438
- response_model=model_class,
439
- max_retries=2, # Automatically retry on validation errors
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
- ) -> AsyncGenerator[Union[str, bytes], None]: # pragma: no cover
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
- ) -> AsyncGenerator[Union[str, bytes], None]:
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
- ) -> AsyncGenerator[Union[str, bytes], None]:
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
- ) -> AsyncGenerator[Union[str, bytes], None]:
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
 
@@ -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
- ) -> AsyncGenerator[Union[str, bytes], None]: # pragma: no cover
233
- """Generate a response using OpenAI function calling (tools API) via generate_text."""
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
- for tool in self.get_agent_tools(agent_name):
271
- functions.append(
272
- {
273
- "name": tool["name"],
274
- "description": tool.get("description", ""),
275
- "parameters": tool.get("parameters", {}),
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
 
@@ -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
- ) -> AsyncGenerator[Union[str, bytes], None]: # pragma: no cover
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
- full_text_response += chunk
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.2.2
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.37)
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.0)
21
+ Requires-Dist: openai (==1.82.1)
22
22
  Requires-Dist: pillow (==11.2.1)
23
- Requires-Dist: pinecone (==7.0.1)
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 with transfers and swaps
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 Transfer
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
- config = {
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
- async for response in solana_agent.process("user123", "Generate an example leetcode medium in Python and give me the zip file."):
863
- print(response, end="")
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=nKfJzgtxNfQWLp6vcu-2Z8zBbvpYgTOEil7nPH7QIlU,23340
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=z_8i_dDJOV5JcZvvRNsRulCd40RvIUuE_f231fRXBDo,8975
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=hFYe04lFGbp4BDlUMOnYQrp_SQXFPcktGOwsi0F87vU,3140
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=IBtvl_p2Dd9pzuA6ub6DZRn50Td8f-XMtcc1M4V3gvA,2872
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=MgLudTwzCzzzSR6PsVTB-w5rhGDHB5B81TGjo2z3G-A,2152
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=eLMMwc8hwHHjxFxlvVvkZfoQi8cSgQycWJbYAVphl9E,1632
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=q5cYzY6Jp5HFtYgJtrqTBWp5Z2n3dXdpQ5YScSKfvPo,18056
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=ENUfs4WSTpODMRXppDVW-Y3li9jYn8pOfQIHIPerUdQ,18498
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.2.2.dist-info/LICENSE,sha256=BnSRc-NSFuyF2s496l_4EyrwAP6YimvxWcjPiJ0J7g4,1057
40
- solana_agent-29.2.2.dist-info/METADATA,sha256=cCliPjVhs1OYUrlewGZDXyRvASDLRKMgrC2g7DPzaYY,36578
41
- solana_agent-29.2.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
42
- solana_agent-29.2.2.dist-info/entry_points.txt,sha256=-AuT_mfqk8dlZ0pHuAjx1ouAWpTRjpqvEUa6YV3lmc0,53
43
- solana_agent-29.2.2.dist-info/RECORD,,
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,,