signalwire-agents 0.1.0__py3-none-any.whl → 0.1.2__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.
Files changed (34) hide show
  1. signalwire_agents/__init__.py +10 -1
  2. signalwire_agents/agent_server.py +73 -44
  3. signalwire_agents/core/__init__.py +9 -0
  4. signalwire_agents/core/agent_base.py +125 -33
  5. signalwire_agents/core/function_result.py +31 -12
  6. signalwire_agents/core/pom_builder.py +9 -0
  7. signalwire_agents/core/security/__init__.py +9 -0
  8. signalwire_agents/core/security/session_manager.py +9 -0
  9. signalwire_agents/core/state/__init__.py +9 -0
  10. signalwire_agents/core/state/file_state_manager.py +9 -0
  11. signalwire_agents/core/state/state_manager.py +9 -0
  12. signalwire_agents/core/swaig_function.py +9 -0
  13. signalwire_agents/core/swml_builder.py +9 -0
  14. signalwire_agents/core/swml_handler.py +9 -0
  15. signalwire_agents/core/swml_renderer.py +9 -0
  16. signalwire_agents/core/swml_service.py +88 -40
  17. signalwire_agents/prefabs/__init__.py +12 -1
  18. signalwire_agents/prefabs/concierge.py +9 -18
  19. signalwire_agents/prefabs/faq_bot.py +9 -18
  20. signalwire_agents/prefabs/info_gatherer.py +193 -183
  21. signalwire_agents/prefabs/receptionist.py +294 -0
  22. signalwire_agents/prefabs/survey.py +9 -18
  23. signalwire_agents/utils/__init__.py +9 -0
  24. signalwire_agents/utils/pom_utils.py +9 -0
  25. signalwire_agents/utils/schema_utils.py +9 -0
  26. signalwire_agents/utils/token_generators.py +9 -0
  27. signalwire_agents/utils/validators.py +9 -0
  28. {signalwire_agents-0.1.0.dist-info → signalwire_agents-0.1.2.dist-info}/METADATA +75 -30
  29. signalwire_agents-0.1.2.dist-info/RECORD +34 -0
  30. {signalwire_agents-0.1.0.dist-info → signalwire_agents-0.1.2.dist-info}/WHEEL +1 -1
  31. signalwire_agents-0.1.2.dist-info/licenses/LICENSE +21 -0
  32. signalwire_agents-0.1.0.dist-info/RECORD +0 -32
  33. {signalwire_agents-0.1.0.data → signalwire_agents-0.1.2.data}/data/schema.json +0 -0
  34. {signalwire_agents-0.1.0.dist-info → signalwire_agents-0.1.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,294 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
10
+ """
11
+ ReceptionistAgent - Prefab agent for greeting callers and transferring them to appropriate departments
12
+ """
13
+
14
+ from typing import List, Dict, Any, Optional, Union
15
+ import json
16
+
17
+ from signalwire_agents.core.agent_base import AgentBase
18
+ from signalwire_agents.core.function_result import SwaigFunctionResult
19
+
20
+
21
+ class ReceptionistAgent(AgentBase):
22
+ """
23
+ A prefab agent designed to act as a receptionist that:
24
+ 1. Greets callers
25
+ 2. Collects basic information about their needs
26
+ 3. Transfers them to the appropriate department
27
+
28
+ Example:
29
+ agent = ReceptionistAgent(
30
+ departments=[
31
+ {"name": "sales", "description": "For product inquiries, pricing, and purchasing", "number": "+15551235555"},
32
+ {"name": "support", "description": "For technical help and troubleshooting", "number": "+15551236666"}
33
+ ]
34
+ )
35
+ """
36
+
37
+ def __init__(
38
+ self,
39
+ departments: List[Dict[str, str]],
40
+ name: str = "receptionist",
41
+ route: str = "/receptionist",
42
+ greeting: str = "Thank you for calling. How can I help you today?",
43
+ voice: str = "elevenlabs.josh",
44
+ **kwargs
45
+ ):
46
+ """
47
+ Initialize a receptionist agent
48
+
49
+ Args:
50
+ departments: List of departments to transfer to, each with:
51
+ - name: Department identifier (e.g., "sales")
52
+ - description: Description of department's purpose
53
+ - number: Phone number for transfer
54
+ name: Agent name for the route
55
+ route: HTTP route for this agent
56
+ greeting: Initial greeting message
57
+ voice: Voice ID to use
58
+ **kwargs: Additional arguments for AgentBase
59
+ """
60
+ # Initialize the base agent
61
+ super().__init__(
62
+ name=name,
63
+ route=route,
64
+ use_pom=True,
65
+ **kwargs
66
+ )
67
+
68
+ # Validate departments format
69
+ self._validate_departments(departments)
70
+
71
+ # Store greeting
72
+ self._greeting = greeting
73
+
74
+ # Set up global data with departments and initial state
75
+ self.set_global_data({
76
+ "departments": departments,
77
+ "caller_info": {}
78
+ })
79
+
80
+ # Build a prompt
81
+ self._build_prompt()
82
+
83
+ # Configure agent settings
84
+ self._configure_agent_settings(voice)
85
+
86
+ # Register tools
87
+ self._register_tools()
88
+
89
+ def _validate_departments(self, departments):
90
+ """Validate that departments are in the correct format"""
91
+ if not departments:
92
+ raise ValueError("At least one department is required")
93
+
94
+ for i, dept in enumerate(departments):
95
+ if "name" not in dept:
96
+ raise ValueError(f"Department {i+1} is missing 'name' field")
97
+ if "description" not in dept:
98
+ raise ValueError(f"Department {i+1} is missing 'description' field")
99
+ if "number" not in dept:
100
+ raise ValueError(f"Department {i+1} is missing 'number' field")
101
+
102
+ def _build_prompt(self):
103
+ """Build the agent's prompt with personality, goals, and instructions"""
104
+
105
+ # Set personality
106
+ self.prompt_add_section(
107
+ "Personality",
108
+ body="You are a friendly and professional receptionist. You speak clearly and efficiently while maintaining a warm, helpful tone."
109
+ )
110
+
111
+ # Set goal
112
+ self.prompt_add_section(
113
+ "Goal",
114
+ body="Your goal is to greet callers, collect their basic information, and transfer them to the appropriate department."
115
+ )
116
+
117
+ # Set instructions
118
+ self.prompt_add_section(
119
+ "Instructions",
120
+ bullets=[
121
+ f"Begin by greeting the caller with: '{self._greeting}'",
122
+ "Collect their name and a brief description of their needs.",
123
+ "Based on their needs, determine which department would be most appropriate.",
124
+ "Use the collect_caller_info function when you have their name and reason for calling.",
125
+ "Use the transfer_call function to transfer them to the appropriate department.",
126
+ "Before transferring, always confirm with the caller that they're being transferred to the right department.",
127
+ "If a caller's request doesn't clearly match a department, ask follow-up questions to clarify."
128
+ ]
129
+ )
130
+
131
+ # Add context with department information
132
+ global_data = self._global_data
133
+ departments = global_data.get("departments", [])
134
+
135
+ department_bullets = []
136
+ for dept in departments:
137
+ department_bullets.append(f"{dept['name']}: {dept['description']}")
138
+
139
+ self.prompt_add_section(
140
+ "Available Departments",
141
+ bullets=department_bullets
142
+ )
143
+
144
+ # Add a post-prompt for summary generation
145
+ self.set_post_prompt("""
146
+ Return a JSON summary of the conversation:
147
+ {
148
+ "caller_name": "CALLER'S NAME",
149
+ "reason": "REASON FOR CALLING",
150
+ "department": "DEPARTMENT TRANSFERRED TO",
151
+ "satisfaction": "high/medium/low (estimated caller satisfaction)"
152
+ }
153
+ """)
154
+
155
+ def _configure_agent_settings(self, voice):
156
+ """Configure additional agent settings"""
157
+
158
+ # Set AI behavior parameters
159
+ self.set_params({
160
+ "end_of_speech_timeout": 700,
161
+ "speech_event_timeout": 1000,
162
+ "transfer_summary": True # Enable call summary transfer between agents
163
+ })
164
+
165
+ # Set language with specified voice
166
+ self.add_language(
167
+ name="English",
168
+ code="en-US",
169
+ voice=voice,
170
+ speech_fillers=["Let me get that information for you...", "One moment please..."],
171
+ function_fillers=["I'm processing that...", "Let me check which department can help you best..."]
172
+ )
173
+
174
+ def _register_tools(self):
175
+ """Register the tools this agent needs"""
176
+
177
+ # Define collect_caller_info tool
178
+ self.define_tool(
179
+ name="collect_caller_info",
180
+ description="Collect the caller's information for routing",
181
+ parameters={
182
+ "name": {
183
+ "type": "string",
184
+ "description": "The caller's name"
185
+ },
186
+ "reason": {
187
+ "type": "string",
188
+ "description": "The reason for the call"
189
+ }
190
+ },
191
+ handler=self._collect_caller_info_handler
192
+ )
193
+
194
+ # Define transfer_call tool
195
+ # First, get the department names from global data
196
+ global_data = self._global_data
197
+ departments = global_data.get("departments", [])
198
+ department_names = [dept["name"] for dept in departments]
199
+
200
+ self.define_tool(
201
+ name="transfer_call",
202
+ description="Transfer the caller to the appropriate department",
203
+ parameters={
204
+ "department": {
205
+ "type": "string",
206
+ "description": "The department to transfer to",
207
+ "enum": department_names
208
+ }
209
+ },
210
+ handler=self._transfer_call_handler
211
+ )
212
+
213
+ def _collect_caller_info_handler(self, args, raw_data):
214
+ """Handler for collect_caller_info tool"""
215
+
216
+ # Get the caller info
217
+ name = args.get("name", "")
218
+ reason = args.get("reason", "")
219
+
220
+ # Create response with global data update
221
+ result = SwaigFunctionResult(
222
+ f"Thank you, {name}. I've noted that you're calling about {reason}."
223
+ )
224
+
225
+ # Update global data with caller info
226
+ result.add_actions([
227
+ {"set_global_data": {
228
+ "caller_info": {
229
+ "name": name,
230
+ "reason": reason
231
+ }
232
+ }}
233
+ ])
234
+
235
+ return result
236
+
237
+ def _transfer_call_handler(self, args, raw_data):
238
+ """Handler for transfer_call tool"""
239
+
240
+ # Get the department
241
+ department_name = args.get("department", "")
242
+
243
+ # Get global data
244
+ global_data = raw_data.get("global_data", {})
245
+ caller_info = global_data.get("caller_info", {})
246
+ name = caller_info.get("name", "the caller")
247
+ departments = global_data.get("departments", [])
248
+
249
+ # Find the department in the list
250
+ department = None
251
+ for dept in departments:
252
+ if dept["name"] == department_name:
253
+ department = dept
254
+ break
255
+
256
+ # If department not found, return error
257
+ if not department:
258
+ return SwaigFunctionResult(f"Sorry, I couldn't find the {department_name} department.")
259
+
260
+ # Get transfer number
261
+ transfer_number = department.get("number", "")
262
+
263
+ # Create message for caller
264
+ message = f"I'll transfer you to our {department_name} department now. Thank you for calling, {name}!"
265
+
266
+ # Create result with transfer SWML
267
+ result = SwaigFunctionResult(message)
268
+
269
+ # Add the SWML to execute the transfer
270
+ result.add_swml([
271
+ {
272
+ "play": {
273
+ "url": f"say:{message}"
274
+ }
275
+ },
276
+ {
277
+ "connect": {
278
+ "to": transfer_number
279
+ }
280
+ }
281
+ ])
282
+
283
+ return result
284
+
285
+ def on_summary(self, summary, raw_data=None):
286
+ """
287
+ Process the conversation summary
288
+
289
+ Args:
290
+ summary: Summary data from the conversation
291
+ raw_data: The complete raw POST data from the request
292
+ """
293
+ # Subclasses can override this to handle the summary
294
+ pass
@@ -1,3 +1,12 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
1
10
  """
2
11
  SurveyAgent - Prefab agent for conducting automated surveys
3
12
  """
@@ -51,7 +60,6 @@ class SurveyAgent(AgentBase):
51
60
  conclusion: Optional[str] = None,
52
61
  brand_name: Optional[str] = None,
53
62
  max_retries: int = 2,
54
- schema_path: Optional[str] = None,
55
63
  **kwargs
56
64
  ):
57
65
  """
@@ -70,30 +78,13 @@ class SurveyAgent(AgentBase):
70
78
  conclusion: Optional custom conclusion message
71
79
  brand_name: Optional brand or company name
72
80
  max_retries: Maximum number of times to retry invalid answers
73
- schema_path: Optional path to a custom schema
74
81
  **kwargs: Additional arguments for AgentBase
75
82
  """
76
- # Find schema.json if not provided
77
- if not schema_path:
78
- current_dir = os.path.dirname(os.path.abspath(__file__))
79
- parent_dir = os.path.dirname(os.path.dirname(current_dir))
80
-
81
- schema_locations = [
82
- os.path.join(current_dir, "schema.json"),
83
- os.path.join(parent_dir, "schema.json")
84
- ]
85
-
86
- for loc in schema_locations:
87
- if os.path.exists(loc):
88
- schema_path = loc
89
- break
90
-
91
83
  # Initialize the base agent
92
84
  super().__init__(
93
85
  name="survey",
94
86
  route="/survey",
95
87
  use_pom=True,
96
- schema_path=schema_path,
97
88
  **kwargs
98
89
  )
99
90
 
@@ -0,0 +1,9 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
@@ -0,0 +1,9 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
@@ -1,3 +1,12 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
1
10
  """
2
11
  Utilities for working with the SWML JSON schema.
3
12
 
@@ -0,0 +1,9 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
@@ -0,0 +1,9 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: signalwire_agents
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: SignalWire AI Agents SDK
5
5
  Author-email: SignalWire Team <info@signalwire.com>
6
6
  Project-URL: Homepage, https://github.com/signalwire/signalwire-ai-agents
@@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.10
15
15
  Classifier: Programming Language :: Python :: 3.11
16
16
  Requires-Python: >=3.7
17
17
  Description-Content-Type: text/markdown
18
+ License-File: LICENSE
18
19
  Requires-Dist: fastapi==0.115.12
19
20
  Requires-Dist: pydantic==2.11.4
20
21
  Requires-Dist: PyYAML==6.0.2
@@ -23,6 +24,7 @@ Requires-Dist: setuptools==66.1.1
23
24
  Requires-Dist: signalwire_pom==2.7.1
24
25
  Requires-Dist: structlog==25.3.0
25
26
  Requires-Dist: uvicorn==0.34.2
27
+ Dynamic: license-file
26
28
 
27
29
  # SignalWire AI Agent SDK
28
30
 
@@ -33,8 +35,9 @@ A Python SDK for creating, hosting, and securing SignalWire AI agents as microse
33
35
  - **Self-Contained Agents**: Each agent is both a web app and an AI persona
34
36
  - **Prompt Object Model**: Structured prompt composition using POM
35
37
  - **SWAIG Integration**: Easily define and handle AI tools/functions
36
- - **Security Built-In**: Session management, per-call tokens, and basic auth
37
- - **State Management**: Persistent conversation state with lifecycle hooks
38
+ - **Custom Routing**: Dynamic request handling for different paths and content
39
+ - **Security Built-In**: Session management, function-specific security tokens, and basic auth
40
+ - **State Management**: Persistent conversation state with automatic tracking
38
41
  - **Prefab Archetypes**: Ready-to-use agent types for common scenarios
39
42
  - **Multi-Agent Support**: Host multiple agents on a single server
40
43
 
@@ -53,12 +56,23 @@ from signalwire_agents.core.function_result import SwaigFunctionResult
53
56
  class SimpleAgent(AgentBase):
54
57
  def __init__(self):
55
58
  super().__init__(name="simple", route="/simple")
56
- self.set_personality("You are a helpful assistant.")
57
- self.set_goal("Help users with basic questions.")
58
- self.add_instruction("Be concise and clear.")
59
+
60
+ # Configure the agent's personality
61
+ self.prompt_add_section("Personality", body="You are a helpful assistant.")
62
+ self.prompt_add_section("Goal", body="Help users with basic questions.")
63
+ self.prompt_add_section("Instructions", bullets=["Be concise and clear."])
64
+
65
+ # Alternative using convenience methods:
66
+ # self.setPersonality("You are a helpful assistant.")
67
+ # self.setGoal("Help users with basic questions.")
68
+ # self.setInstructions(["Be concise and clear."])
59
69
 
60
- @AgentBase.tool(name="get_time", parameters={})
61
- def get_time(self):
70
+ @AgentBase.tool(
71
+ name="get_time",
72
+ description="Get the current time",
73
+ parameters={}
74
+ )
75
+ def get_time(self, args, raw_data):
62
76
  from datetime import datetime
63
77
  now = datetime.now().strftime("%H:%M:%S")
64
78
  return SwaigFunctionResult(f"The current time is {now}")
@@ -73,6 +87,7 @@ if __name__ == "__main__":
73
87
 
74
88
  ```python
75
89
  from signalwire_agents import AgentBase
90
+ from signalwire_agents.core.function_result import SwaigFunctionResult
76
91
  from signalwire_agents.core.state import FileStateManager
77
92
 
78
93
  class StatefulAgent(AgentBase):
@@ -86,21 +101,44 @@ class StatefulAgent(AgentBase):
86
101
  enable_state_tracking=True, # Enable state tracking
87
102
  state_manager=state_manager # Use custom state manager
88
103
  )
104
+
105
+ # When enable_state_tracking=True, startup_hook and hangup_hook
106
+ # are automatically registered to track session lifecycle
89
107
 
90
- # These methods are automatically registered when enable_state_tracking=True
91
- def startup_hook(self, args, raw_data):
92
- """Called when a conversation starts"""
108
+ # Custom tool for accessing and updating state
109
+ @AgentBase.tool(
110
+ name="save_preference",
111
+ description="Save a user preference",
112
+ parameters={
113
+ "preference_name": {
114
+ "type": "string",
115
+ "description": "Name of the preference to save"
116
+ },
117
+ "preference_value": {
118
+ "type": "string",
119
+ "description": "Value of the preference"
120
+ }
121
+ }
122
+ )
123
+ def save_preference(self, args, raw_data):
124
+ # Get the call ID from the raw data
93
125
  call_id = raw_data.get("call_id")
94
- state = self.get_state(call_id) or {}
95
- state["started_at"] = "2023-01-01T12:00:00Z"
96
- self.update_state(call_id, state)
97
- return "Call initialized"
98
126
 
99
- def hangup_hook(self, args, raw_data):
100
- """Called when a conversation ends"""
101
- call_id = raw_data.get("call_id")
102
- state = self.get_state(call_id)
103
- return "Call completed"
127
+ if call_id:
128
+ # Get current state or empty dict if none exists
129
+ state = self.get_state(call_id) or {}
130
+
131
+ # Update the state
132
+ preferences = state.get("preferences", {})
133
+ preferences[args.get("preference_name")] = args.get("preference_value")
134
+ state["preferences"] = preferences
135
+
136
+ # Save the updated state
137
+ self.update_state(call_id, state)
138
+
139
+ return SwaigFunctionResult("Preference saved successfully")
140
+ else:
141
+ return SwaigFunctionResult("Could not save preference: No call ID")
104
142
  ```
105
143
 
106
144
  ## Using Prefab Agents
@@ -113,12 +151,20 @@ agent = InfoGathererAgent(
113
151
  {"name": "full_name", "prompt": "What is your full name?"},
114
152
  {"name": "reason", "prompt": "How can I help you today?"}
115
153
  ],
116
- confirmation_template="Thanks {full_name}, I'll help you with {reason}."
154
+ confirmation_template="Thanks {full_name}, I'll help you with {reason}.",
155
+ name="info-gatherer",
156
+ route="/info-gatherer"
117
157
  )
118
158
 
119
- agent.serve(host="0.0.0.0", port=8000, route="/support")
159
+ agent.serve(host="0.0.0.0", port=8000)
120
160
  ```
121
161
 
162
+ Available prefabs include:
163
+ - `InfoGathererAgent`: Collects structured information from users
164
+ - `FAQBotAgent`: Answers questions based on a knowledge base
165
+ - `ConciergeAgent`: Routes users to specialized agents
166
+ - `SurveyAgent`: Conducts structured surveys with questions and rating scales
167
+
122
168
  ## Configuration
123
169
 
124
170
  ### Environment Variables
@@ -132,6 +178,7 @@ The SDK supports the following environment variables:
132
178
  - `SWML_SSL_CERT_PATH`: Path to SSL certificate file
133
179
  - `SWML_SSL_KEY_PATH`: Path to SSL private key file
134
180
  - `SWML_DOMAIN`: Domain name for SSL certificate and external URLs
181
+ - `SWML_SCHEMA_PATH`: Optional path to override the location of the schema.json file
135
182
 
136
183
  When the auth environment variables are set, they will be used for all agents instead of generating random credentials. The proxy URL base is useful when your service is behind a reverse proxy or when you need external services to access your webhooks.
137
184
 
@@ -139,15 +186,13 @@ To enable HTTPS directly (without a reverse proxy), set `SWML_SSL_ENABLED` to "t
139
186
 
140
187
  ## Documentation
141
188
 
142
- See the [full documentation](https://docs.signalwire.com/ai-agents) for details on:
189
+ The package includes comprehensive documentation in the `docs/` directory:
190
+
191
+ - [Agent Guide](docs/agent_guide.md) - Detailed guide to creating and customizing agents
192
+ - [Architecture](docs/architecture.md) - Overview of the SDK architecture and core concepts
193
+ - [SWML Service Guide](docs/swml_service_guide.md) - Guide to the underlying SWML service
143
194
 
144
- - Creating custom agents
145
- - Using prefab agents
146
- - SWAIG function definitions
147
- - State management and persistence
148
- - Security model
149
- - Deployment options
150
- - Multi-agent hosting
195
+ These documents provide in-depth explanations of the features, APIs, and usage patterns.
151
196
 
152
197
  ## License
153
198
 
@@ -0,0 +1,34 @@
1
+ signalwire_agents/__init__.py,sha256=gZDtAkfd7KIm-6XEXIhNXI553-1Kxks035kcHQFmXjY,800
2
+ signalwire_agents/agent_server.py,sha256=se_YzOQE5UUoRUKCbTnOg9qr4G3qN7iVuQLutwXEwFU,12850
3
+ signalwire_agents/schema.json,sha256=M8Mn6pQda2P9jhbmkALrLr1wt-fRuhYRqdmEi9Rbhqk,178075
4
+ signalwire_agents/core/__init__.py,sha256=mVDLbpq1pg_WwiqsQR28NNZwJ6-VUXFIfg-vN7pk0ew,806
5
+ signalwire_agents/core/agent_base.py,sha256=KIvueG5wIxveyALELISmPLWEkyhW5abU4hxq427ao_o,98466
6
+ signalwire_agents/core/function_result.py,sha256=vD8eBDJBQNNnss1jShadfogCZw_prODB6eBkTuVgZKA,3538
7
+ signalwire_agents/core/pom_builder.py,sha256=ywuiIfP8BeLBPo_G4X1teZlG6zTCMkW71CZnmyoDTAQ,6636
8
+ signalwire_agents/core/swaig_function.py,sha256=WoHGQuCmU9L9k39pttRunmfRtIa_PnNRn9W0Xq3MfIk,6316
9
+ signalwire_agents/core/swml_builder.py,sha256=Y_eHThVVso-_Hz4f73eEuu3HJstsM9PtBl-36GvAXhI,6594
10
+ signalwire_agents/core/swml_handler.py,sha256=KvphI_YY47VWGVXaix_N3SuQSyygHEUr9We6xESQK44,7002
11
+ signalwire_agents/core/swml_renderer.py,sha256=iobMWWoBR7dkHndI3Qlwf4C0fg2p7DmAU2Rb7ZmmLhA,13891
12
+ signalwire_agents/core/swml_service.py,sha256=oZKM9pKPxtbsMp3nYnx5FXtW3igj2Sc2wZbQujNVNrg,42097
13
+ signalwire_agents/core/security/__init__.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
14
+ signalwire_agents/core/security/session_manager.py,sha256=5y0Mr3cI63cO34ctFgq-KX26mdG0Tpr7rTEsgoTS_44,5229
15
+ signalwire_agents/core/state/__init__.py,sha256=qpYIfQBApet6VQsy6diS3yu0lMxCBC6REOUk5l1McUw,379
16
+ signalwire_agents/core/state/file_state_manager.py,sha256=52I_KVlmhHCbKIaHj74Q-ksP_-AF6ewYmOXCf4n5DTQ,7307
17
+ signalwire_agents/core/state/state_manager.py,sha256=76B4mDutMb826dK4c_IJhOXH09BW1bJu6EZa6Mh_LB4,2511
18
+ signalwire_agents/prefabs/__init__.py,sha256=MW11J63XH7KxF2MWguRsMFM9iqMWexaEO9ynDPL_PDM,715
19
+ signalwire_agents/prefabs/concierge.py,sha256=--esvAV1lozQGYXHAqvSg8_TtlIoVfQK75APJ5zqX9I,9779
20
+ signalwire_agents/prefabs/faq_bot.py,sha256=cUuHhnDB8S4aVg-DiQe4jBmCAPrYQrND_Mff9iaeEa0,10572
21
+ signalwire_agents/prefabs/info_gatherer.py,sha256=y9gxjq1vF0-TrE6m734dCcAHqxt0I_DyCqxoM45QY8U,9940
22
+ signalwire_agents/prefabs/receptionist.py,sha256=bYHbdvNepnMYgU6igcKY8AtCl2vBxUf_g6Z_2D1uD4g,10284
23
+ signalwire_agents/prefabs/survey.py,sha256=1pyUeZ5heDqFAYqkYs5fHN_jQ7TKqJInnOOUQEajSsY,14358
24
+ signalwire_agents/utils/__init__.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
25
+ signalwire_agents/utils/pom_utils.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
26
+ signalwire_agents/utils/schema_utils.py,sha256=LvFCFvJTQk_xYK0B-NXbkXKEF7Zmv-LqpV_vfpPnOb4,13473
27
+ signalwire_agents/utils/token_generators.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
28
+ signalwire_agents/utils/validators.py,sha256=4Mr7baQ_xR_hfJ72YxQRAT_GFa663YjFX_PumJ35Xds,191
29
+ signalwire_agents-0.1.2.data/data/schema.json,sha256=M8Mn6pQda2P9jhbmkALrLr1wt-fRuhYRqdmEi9Rbhqk,178075
30
+ signalwire_agents-0.1.2.dist-info/licenses/LICENSE,sha256=NYvAsB-rTcSvG9cqHt9EUHAWLiA9YzM4Qfz-mPdvDR0,1067
31
+ signalwire_agents-0.1.2.dist-info/METADATA,sha256=WzQzw2cTR_5Rs_Gd5ypKcOxej87H81FAfYte-ODskVg,7414
32
+ signalwire_agents-0.1.2.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
33
+ signalwire_agents-0.1.2.dist-info/top_level.txt,sha256=kDGS6ZYv84K9P5Kyg9_S8P_pbUXoHkso0On_DB5bbWc,18
34
+ signalwire_agents-0.1.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.6.0)
2
+ Generator: setuptools (80.7.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 SignalWire
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.