ttp-agent-sdk 2.1.0 → 2.1.2
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.
- package/SIGNED_LINK_GUIDE.md +218 -0
- package/dist/agent-widget.js +1 -1
- package/dist/agent-widget.js.map +1 -1
- package/dist/examples/multi-platform-examples.html +1119 -0
- package/dist/examples/react-example.html +463 -144
- package/examples/multi-platform-examples.html +1119 -0
- package/examples/react-example.html +463 -144
- package/package.json +3 -2
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# TTP Agent SDK - Signed Link Authentication Guide
|
|
2
|
+
|
|
3
|
+
## 🔐 Understanding Signed Links
|
|
4
|
+
|
|
5
|
+
Signed links provide **secure, production-ready authentication** for your voice agents. Your **UI backend** generates secure, time-limited URLs that the widget uses to connect to the **conversation backend**.
|
|
6
|
+
|
|
7
|
+
## 🏗️ Architecture Overview
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
User's Frontend → User's Backend → TTP UI Backend → TTP Conversation Backend
|
|
11
|
+
↓ ↓ ↓ ↓
|
|
12
|
+
Requests Requests Generates Handles
|
|
13
|
+
signed URL signed URL signed URL conversation
|
|
14
|
+
↑ ↑ ↑ ↑
|
|
15
|
+
Receives Receives Returns Validates
|
|
16
|
+
signed URL signed URL signed URL signed token
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**The complete flow:**
|
|
20
|
+
1. **User's Frontend** → requests signed URL from **User's Backend**
|
|
21
|
+
2. **User's Backend** → requests signed URL from **TTP UI Backend** (`/api/public/agents`)
|
|
22
|
+
3. **TTP UI Backend** → generates signed URL and returns to **User's Backend**
|
|
23
|
+
4. **User's Backend** → returns signed URL to **User's Frontend**
|
|
24
|
+
5. **User's Frontend** → connects directly to **TTP Conversation Backend** using signed URL
|
|
25
|
+
|
|
26
|
+
## 🎯 Why Use Signed Links?
|
|
27
|
+
|
|
28
|
+
### ❌ **Direct Agent ID (Insecure)**
|
|
29
|
+
```javascript
|
|
30
|
+
// DON'T DO THIS IN PRODUCTION
|
|
31
|
+
new EnhancedAgentWidget({
|
|
32
|
+
agentId: 'agent_12345', // ❌ Visible in network traffic
|
|
33
|
+
websocketUrl: 'wss://speech.talktopc.com/ws/conv'
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Problems:**
|
|
38
|
+
- Agent ID exposed in browser network tab
|
|
39
|
+
- No cost control
|
|
40
|
+
- No user-specific permissions
|
|
41
|
+
- Security risk
|
|
42
|
+
|
|
43
|
+
### ✅ **Signed Link (Secure)**
|
|
44
|
+
```javascript
|
|
45
|
+
// PRODUCTION-READY APPROACH
|
|
46
|
+
new EnhancedAgentWidget({
|
|
47
|
+
agentId: 'agent_12345',
|
|
48
|
+
getSessionUrl: async ({ agentId, variables }) => {
|
|
49
|
+
// User's Frontend calls User's Backend
|
|
50
|
+
const response = await fetch('/api/get-voice-session', {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: { 'Content-Type': 'application/json' },
|
|
53
|
+
body: JSON.stringify({ agentId, variables })
|
|
54
|
+
});
|
|
55
|
+
const data = await response.json();
|
|
56
|
+
return data.signedUrl; // ✅ Secure, time-limited URL from TTP
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Benefits:**
|
|
62
|
+
- ✅ Secure authentication
|
|
63
|
+
- ✅ Cost control per user
|
|
64
|
+
- ✅ User-specific permissions
|
|
65
|
+
- ✅ Time-limited access
|
|
66
|
+
- ✅ Production-ready
|
|
67
|
+
|
|
68
|
+
## 🏗️ Implementation Guide
|
|
69
|
+
|
|
70
|
+
### Step 1: User's Backend Implementation
|
|
71
|
+
|
|
72
|
+
Your user's backend should have an endpoint that requests signed URLs from TTP:
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
// User's Backend (Node.js example)
|
|
76
|
+
app.post('/api/get-voice-session', async (req, res) => {
|
|
77
|
+
try {
|
|
78
|
+
const { agentId, variables } = req.body;
|
|
79
|
+
|
|
80
|
+
// Validate user authentication
|
|
81
|
+
const user = await validateUser(req.headers.authorization);
|
|
82
|
+
if (!user) {
|
|
83
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Request signed URL from TTP UI Backend
|
|
87
|
+
const ttpResponse = await fetch('https://backend.talktopc.com/api/public/agents', {
|
|
88
|
+
method: 'POST',
|
|
89
|
+
headers: {
|
|
90
|
+
'Content-Type': 'application/json',
|
|
91
|
+
'Authorization': `Bearer ${process.env.TTP_API_KEY}` // Your TTP API key
|
|
92
|
+
},
|
|
93
|
+
body: JSON.stringify({
|
|
94
|
+
agentId,
|
|
95
|
+
variables: {
|
|
96
|
+
...variables,
|
|
97
|
+
userId: user.id,
|
|
98
|
+
userEmail: user.email
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (!ttpResponse.ok) {
|
|
104
|
+
throw new Error(`TTP API error: ${ttpResponse.status}`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const ttpData = await ttpResponse.json();
|
|
108
|
+
|
|
109
|
+
// Return signed URL to user's frontend
|
|
110
|
+
res.json({
|
|
111
|
+
signedUrl: ttpData.signedUrl
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error('Failed to get signed URL from TTP:', error);
|
|
116
|
+
res.status(500).json({ error: 'Failed to get voice session' });
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Step 2: User's Frontend Integration
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
import { EnhancedAgentWidget } from 'ttp-agent-sdk';
|
|
125
|
+
|
|
126
|
+
new EnhancedAgentWidget({
|
|
127
|
+
agentId: 'your_agent_id',
|
|
128
|
+
|
|
129
|
+
// User's Frontend calls User's Backend
|
|
130
|
+
getSessionUrl: async ({ agentId, variables }) => {
|
|
131
|
+
try {
|
|
132
|
+
const response = await fetch('/api/get-voice-session', {
|
|
133
|
+
method: 'POST',
|
|
134
|
+
headers: {
|
|
135
|
+
'Content-Type': 'application/json',
|
|
136
|
+
'Authorization': `Bearer ${getAuthToken()}` // User's auth token
|
|
137
|
+
},
|
|
138
|
+
body: JSON.stringify({
|
|
139
|
+
agentId,
|
|
140
|
+
variables: {
|
|
141
|
+
...variables,
|
|
142
|
+
page: 'homepage',
|
|
143
|
+
userType: 'customer'
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
if (!response.ok) {
|
|
149
|
+
throw new Error(`Your backend responded with ${response.status}`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const data = await response.json();
|
|
153
|
+
return data.signedUrl; // This connects directly to TTP Conversation Backend
|
|
154
|
+
|
|
155
|
+
} catch (error) {
|
|
156
|
+
console.error('Failed to get signed URL from your backend:', error);
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
variables: {
|
|
162
|
+
page: 'homepage',
|
|
163
|
+
userType: 'customer',
|
|
164
|
+
language: 'en'
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## 🔧 Your Current Implementation
|
|
170
|
+
|
|
171
|
+
Based on your setup, you're already using this pattern:
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
// Your current LandingPageWidget.jsx
|
|
175
|
+
getSessionUrl: async ({ agentId, variables }) => {
|
|
176
|
+
const response = await fetch(buildApiUrl('/api/landing/signed-url'), {
|
|
177
|
+
method: 'POST',
|
|
178
|
+
headers: { 'Content-Type': 'application/json' },
|
|
179
|
+
body: JSON.stringify({
|
|
180
|
+
agentId: agentId,
|
|
181
|
+
variables: variables,
|
|
182
|
+
page: 'landing',
|
|
183
|
+
userType: 'visitor'
|
|
184
|
+
})
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
const data = await response.json();
|
|
188
|
+
return data.signedUrl; // This connects to conversation backend
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## 🎯 Key Points
|
|
193
|
+
|
|
194
|
+
1. **UI Backend** (`/api/landing/signed-url`):
|
|
195
|
+
- Handles authentication
|
|
196
|
+
- Generates signed URLs
|
|
197
|
+
- Manages user permissions
|
|
198
|
+
- Controls costs
|
|
199
|
+
|
|
200
|
+
2. **Conversation Backend** (`wss://speech.talktopc.com/ws/conv`):
|
|
201
|
+
- Validates signed tokens
|
|
202
|
+
- Handles voice conversations
|
|
203
|
+
- Processes audio streams
|
|
204
|
+
|
|
205
|
+
3. **Frontend Widget**:
|
|
206
|
+
- Requests signed URL from UI backend
|
|
207
|
+
- Connects to conversation backend using signed URL
|
|
208
|
+
- Never exposes agent IDs directly
|
|
209
|
+
|
|
210
|
+
## 🚀 Production Benefits
|
|
211
|
+
|
|
212
|
+
- **Security**: Agent IDs never exposed in frontend
|
|
213
|
+
- **Separation**: UI logic separate from conversation logic
|
|
214
|
+
- **Scalability**: Each backend can scale independently
|
|
215
|
+
- **Control**: UI backend controls access and permissions
|
|
216
|
+
- **Monitoring**: Track usage and costs at UI backend level
|
|
217
|
+
|
|
218
|
+
This architecture ensures your voice agents are secure, scalable, and production-ready! 🎤✨
|