@squidcloud/cli 1.0.445 → 1.0.447

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.
@@ -0,0 +1,773 @@
1
+ # AI Features
2
+
3
+ Squid provides comprehensive AI capabilities including agents, knowledge bases, image/audio processing, and AI-powered queries.
4
+
5
+ **REST API:** Most AI features are also available via REST API. See [api.md](api.md) or https://docs.getsquid.ai/reference-docs/api/
6
+
7
+ ## Contents
8
+ - Supported Models
9
+ - AI Agents
10
+ - Knowledge Bases
11
+ - AI Files
12
+ - Image & Audio
13
+ - AI Query & API Call
14
+ - Application Settings
15
+ - Backend Decorators
16
+ - MCP (Model Context Protocol)
17
+ - LLM Services
18
+ - AI Functions Configurator
19
+
20
+ ## Supported Models
21
+
22
+ Squid supports multiple AI providers and models. The available models are defined as TypeScript constants:
23
+
24
+ ```typescript
25
+ import {
26
+ // Chat model constants (by provider)
27
+ OPENAI_CHAT_MODEL_NAMES,
28
+ ANTHROPIC_CHAT_MODEL_NAMES,
29
+ GEMINI_CHAT_MODEL_NAMES,
30
+ GROK_CHAT_MODEL_NAMES,
31
+ VENDOR_AI_CHAT_MODEL_NAMES, // All chat models combined
32
+
33
+ // Embedding model constants
34
+ AI_EMBEDDINGS_MODEL_NAMES,
35
+ OPENAI_EMBEDDINGS_MODEL_NAMES,
36
+ VOYAGE_EMBEDDING_MODEL_NAMES,
37
+
38
+ // Image generation model constants
39
+ AI_IMAGE_MODEL_NAMES,
40
+ OPENAI_IMAGE_MODEL_NAMES,
41
+ STABLE_DIFFUSION_MODEL_NAMES,
42
+ FLUX_MODEL_NAMES,
43
+
44
+ // Audio model constants
45
+ AI_AUDIO_TRANSCRIPTION_MODEL_NAMES,
46
+ OPENAI_AUDIO_CREATE_SPEECH_MODEL_NAMES,
47
+
48
+ // Type definitions
49
+ AiChatModelName,
50
+ AiEmbeddingsModelName,
51
+ AiImageModelName,
52
+ AiAudioTranscriptionModelName,
53
+ AiAudioCreateSpeechModelName,
54
+ } from '@squidcloud/client';
55
+ ```
56
+
57
+ **Model Categories:**
58
+ - **Chat Models**: Used for AI Agents, AI Query, etc. (OpenAI, Anthropic, Gemini, Grok)
59
+ - **Embedding Models**: Used for Knowledge Bases (OpenAI, Voyage)
60
+ - **Image Generation Models**: Used for image creation (DALL-E, Stable Diffusion, Flux)
61
+ - **Audio Models**: Transcription (Whisper, GPT-4o) and Text-to-Speech (TTS-1, GPT-4o-mini-tts)
62
+
63
+ ## AI Agents
64
+
65
+ AI Agents are powerful, configurable AI assistants that can interact with your data, call functions, connect to integrations, and collaborate with other agents.
66
+
67
+ REST API: [Agent API](https://docs.getsquid.ai/reference-docs/api/#tag/Agent) | OpenAI-specific features: [openai.md](openai.md)
68
+
69
+ ### Agent Capabilities
70
+
71
+ An AI Agent can:
72
+ - Maintain conversation history (**memory is enabled by default**)
73
+ - Call backend functions decorated with `@aiFunction`
74
+ - Query databases and APIs through connected integrations
75
+ - Search knowledge bases for relevant information
76
+ - Collaborate with other AI agents
77
+ - Process voice input and generate voice output
78
+ - Accept files as part of chat requests
79
+
80
+ ### Creating and Managing Agents
81
+
82
+ ```typescript
83
+ const aiClient = squid.ai();
84
+
85
+ // Get the built-in agent (no ID required)
86
+ const builtInAgent = aiClient.agent();
87
+
88
+ // Get a custom agent by ID
89
+ const myAgent = aiClient.agent('my-agent-id');
90
+
91
+ // Get an agent with an Agent API key (allows calling without App API key, bypasses @secureAiAgent methods)
92
+ const agentWithKey = aiClient.agent('my-agent-id', {
93
+ apiKey: 'your-agent-api-key'
94
+ });
95
+
96
+ // Create or update an agent
97
+ await myAgent.upsert({
98
+ description: 'Customer support assistant',
99
+ isPublic: false, // Whether the agent is publicly accessible
100
+ auditLog: true, // Enable audit logging for compliance
101
+ options: {
102
+ model: 'gpt-5-mini', // or 'claude-sonnet-4-5-20250929', 'gemini-3-flash'
103
+ instructions: 'You are a helpful customer support assistant. Be concise and professional.',
104
+ temperature: 0.7
105
+ }
106
+ });
107
+
108
+ // Get agent details
109
+ const agentInfo = await myAgent.get();
110
+ console.log(agentInfo.id, agentInfo.description, agentInfo.options.model);
111
+
112
+ // Update specific properties
113
+ await myAgent.updateInstructions('You are a technical support specialist.');
114
+ await myAgent.updateModel('claude-sonnet-4-5-20250929');
115
+ await myAgent.updateGuardrails(['no-harmful-content']);
116
+
117
+ // Delete an agent
118
+ await myAgent.delete();
119
+
120
+ // List all agents
121
+ const agents = await squid.ai().listAgents();
122
+ agents.forEach(agent => console.log(`${agent.id}: ${agent.description}`));
123
+
124
+ // Manage agent API keys
125
+ const apiKey = await myAgent.regenerateApiKey();
126
+ console.log('New API key:', apiKey);
127
+
128
+ const existingKey = await myAgent.getApiKey();
129
+ console.log('Current API key:', existingKey);
130
+
131
+ // Update agent options at specific path
132
+ await myAgent.setAgentOptionInPath('temperature', 0.9);
133
+ await myAgent.setAgentOptionInPath('options.maxTokens', 2000);
134
+
135
+ // Update connected agents
136
+ await myAgent.updateConnectedAgents([
137
+ { agentId: 'helper-agent', description: 'Helps with tasks' }
138
+ ]);
139
+
140
+ // Update or delete custom guardrails
141
+ await myAgent.updateCustomGuardrails('Never reveal sensitive information');
142
+ await myAgent.deleteCustomGuardrail();
143
+ ```
144
+
145
+ ### Agent Lifecycle
146
+
147
+ 1. **Creation** - Use `upsert()` to create a new agent with an ID
148
+ 2. **Active** - Agent can process requests
149
+ 3. **Update** - Use `upsert()` or specific update methods
150
+ 4. **Deletion** - Use `delete()` to permanently remove the agent
151
+
152
+ **Important Notes:**
153
+ - Agent IDs are permanent - once created, you cannot change the ID
154
+ - Deleting an agent does not delete associated chat history
155
+ - The built-in agent (accessed via `agent()` with no ID) cannot be deleted
156
+ - **Agent API Keys**: You can pass an options object with an `apiKey` when calling `agent()`:
157
+ - Allows calling agent methods without requiring an App API key
158
+ - Bypasses any `@secureAiAgent` security methods when calling agent ask functions
159
+ - Useful for direct agent access without app-level authentication
160
+
161
+ ### Connecting Resources to Agents
162
+
163
+ Agents become powerful when connected to resources:
164
+ - **Other AI agents** (`connectedAgents`) - Agent collaboration
165
+ - **Backend functions** (`functions`) - Custom logic via `@aiFunction` decorators
166
+ - **Integrations** (`connectedIntegrations`) - Database/API queries
167
+ - **Knowledge bases** (`connectedKnowledgeBases`) - RAG (Retrieval Augmented Generation)
168
+
169
+ #### Connected Agents
170
+
171
+ Allow one agent to call another agent as a specialized sub-task handler.
172
+
173
+ ```typescript
174
+ const response = await agent.ask('Analyze our sales data and send report to team', {
175
+ connectedAgents: [
176
+ {
177
+ agentId: 'data-analyst-agent',
178
+ description: 'Analyzes sales data and generates reports'
179
+ },
180
+ {
181
+ agentId: 'email-sender-agent',
182
+ description: 'Sends emails to team members'
183
+ }
184
+ ]
185
+ });
186
+ ```
187
+
188
+ #### Functions
189
+
190
+ Connect backend functions decorated with `@aiFunction` that the agent can call.
191
+
192
+ ```typescript
193
+ // Backend function
194
+ @aiFunction('Gets current inventory for a product', [
195
+ { name: 'productId', type: 'string', required: true, description: 'Product ID' }
196
+ ])
197
+ async getInventory({ productId }: { productId: string }): Promise<number> {
198
+ return await db.inventory.get(productId);
199
+ }
200
+
201
+ // Client - Agent uses the function
202
+ const response = await agent.ask('How many units of product-123 do we have?', {
203
+ functions: ['getInventory'] // Function name or ID
204
+ });
205
+
206
+ // With predefined parameters (hidden from AI)
207
+ const response = await agent.ask('Send notification', {
208
+ functions: [
209
+ {
210
+ functionId: 'sendEmail',
211
+ context: { apiKey: 'secret-key' } // Passed to function but hidden from AI
212
+ }
213
+ ]
214
+ });
215
+ ```
216
+
217
+ #### Connected Integrations
218
+
219
+ Connect database or API integrations so the agent can query them directly.
220
+
221
+ ```typescript
222
+ const response = await agent.ask('Show me active users from last week', {
223
+ connectedIntegrations: [
224
+ {
225
+ integrationId: 'postgres-db',
226
+ integrationType: 'database',
227
+ description: 'Main application database with users, orders, and products',
228
+ instructions: 'Only query the users table unless explicitly asked otherwise',
229
+ options: {
230
+ // Integration-specific options
231
+ }
232
+ },
233
+ {
234
+ integrationId: 'stripe-api',
235
+ integrationType: 'api',
236
+ description: 'Stripe payment API for retrieving payment information'
237
+ }
238
+ ]
239
+ });
240
+ ```
241
+
242
+ #### Connected Knowledge Bases
243
+
244
+ Connect knowledge bases for RAG - agent retrieves relevant context before answering.
245
+
246
+ ```typescript
247
+ const response = await agent.ask('What is our return policy?', {
248
+ connectedKnowledgeBases: [
249
+ {
250
+ knowledgeBaseId: 'company-policies-kb',
251
+ description: 'Use this when asked about company policies, procedures, or guidelines'
252
+ },
253
+ {
254
+ knowledgeBaseId: 'product-docs-kb',
255
+ description: 'Use this when asked about product features, specifications, or usage'
256
+ }
257
+ ]
258
+ });
259
+ ```
260
+
261
+ ### Agent Chat Methods
262
+
263
+ ```typescript
264
+ const agent = squid.ai().agent('my-agent');
265
+
266
+ // Chat (streaming) - Returns RxJS Observable
267
+ // IMPORTANT: Streaming behavior:
268
+ // - NO connected resources: streams token-by-token
269
+ // - HAS connected resources: emits ONCE with complete response
270
+ const chatObs = agent.chat('What is your return policy?', {
271
+ // Memory management
272
+ memoryOptions: {
273
+ memoryMode: 'read-write', // 'none' | 'read-only' | 'read-write'
274
+ memoryId: 'user-123', // Unique per user/session
275
+ expirationMinutes: 1440 // 24 hours
276
+ },
277
+
278
+ // Connected resources (can also be set on agent.upsert)
279
+ connectedAgents: [{ agentId: 'specialist-agent', description: 'Handles X' }],
280
+ functions: ['function1', 'function2'],
281
+ connectedIntegrations: [{ integrationId: 'db', integrationType: 'database', description: '...' }],
282
+ connectedKnowledgeBases: [{ knowledgeBaseId: 'kb1', description: 'When to use this KB' }],
283
+
284
+ // Model & generation
285
+ model: 'gpt-5-mini', // Override agent's default model
286
+ temperature: 0.7,
287
+ maxTokens: 4000,
288
+ maxOutputTokens: 2000,
289
+ instructions: 'Additional instructions for this request only',
290
+ responseFormat: 'json_object', // or 'text'
291
+ verbosity: 'medium', // 'low' | 'medium' | 'high' (OpenAI only)
292
+ reasoningEffort: 'high', // 'minimal' | 'low' | 'medium' | 'high' (for reasoning models)
293
+
294
+ // Context & RAG
295
+ disableContext: false,
296
+ enablePromptRewriteForRag: false,
297
+ includeReference: false,
298
+ contextMetadataFilterForKnowledgeBase: {
299
+ 'kb-id': { category: 'documentation' }
300
+ },
301
+
302
+ // Guardrails & quotas
303
+ guardrails: ['no-harmful-content', 'no-pii'],
304
+ quotas: {
305
+ maxAiCallStackSize: 5
306
+ },
307
+
308
+ // Files & voice
309
+ fileUrls: [
310
+ { id: 'file1', type: 'image', purpose: 'context', url: 'https://...', description: 'Product image' }
311
+ ],
312
+ voiceOptions: {
313
+ modelName: 'tts-1',
314
+ voice: 'alloy', // alloy, ash, ballad, coral, echo, fable, onyx, nova, sage, shimmer, verse
315
+ speed: 1.0
316
+ },
317
+
318
+ // Advanced
319
+ smoothTyping: true,
320
+ useCodeInterpreter: 'llm', // 'none' | 'llm' (OpenAI/Gemini only)
321
+ executionPlanOptions: {
322
+ enabled: true,
323
+ model: 'gpt-5-mini',
324
+ reasoningEffort: 'high',
325
+ allowClarificationQuestions: false
326
+ },
327
+ agentContext: { userId: '123', role: 'admin' },
328
+ includeMetadata: false
329
+ });
330
+
331
+ chatObs.subscribe(text => {
332
+ console.log(text);
333
+ });
334
+
335
+ // Ask (complete response - same options as chat)
336
+ const response = await agent.ask('Question?', { /* same options */ });
337
+
338
+ // Ask with annotations (includes file references, citations)
339
+ const result = await agent.askWithAnnotations('Question?', { /* same options */ });
340
+ console.log(result.responseString);
341
+ console.log(result.annotations);
342
+
343
+ // Ask asynchronously (doesn't wait for response, uses job system)
344
+ await agent.askAsync('Long running task', 'job-id-123', { /* same options */ });
345
+ // Check job status later with squid.job().getJob('job-id-123')
346
+
347
+ // Voice responses
348
+ const voiceResult = await agent.askWithVoiceResponse('Hello', {
349
+ voiceOptions: { modelName: 'tts-1', voice: 'alloy', speed: 1.0 }
350
+ });
351
+ console.log(voiceResult.responseString);
352
+ console.log(voiceResult.voiceResponseFile);
353
+
354
+ // Transcribe audio and chat
355
+ const transcribeResult = await agent.transcribeAndChat(audioFile);
356
+ console.log(transcribeResult.transcribedPrompt);
357
+ transcribeResult.responseStream.subscribe(text => console.log(text));
358
+
359
+ // Transcribe audio and ask (non-streaming)
360
+ const askResult = await agent.transcribeAndAsk(audioFile, { /* ask options */ });
361
+ console.log(askResult.transcribedPrompt);
362
+ console.log(askResult.response);
363
+
364
+ // Transcribe audio and get voice response
365
+ const voiceResponse = await agent.transcribeAndAskWithVoiceResponse(audioFile, {
366
+ voiceOptions: { modelName: 'tts-1', voice: 'alloy' }
367
+ });
368
+ console.log(voiceResponse.transcribedPrompt);
369
+ console.log(voiceResponse.responseString);
370
+ console.log(voiceResponse.voiceResponseFile);
371
+
372
+ // Get chat history
373
+ const history = await agent.getChatHistory('memory-id-123');
374
+
375
+ // Provide feedback on responses
376
+ await agent.provideFeedback('Great response! Very helpful.');
377
+
378
+ // Observe status updates (for long-running operations)
379
+ agent.observeStatusUpdates().subscribe(status => {
380
+ console.log(status.title, status.tags);
381
+ });
382
+ ```
383
+
384
+ ## Knowledge Bases
385
+
386
+ Knowledge bases store and index documents for RAG. REST API: [KnowledgeBase API](https://docs.getsquid.ai/reference-docs/api/#tag/KnowledgeBase)
387
+
388
+ ```typescript
389
+ const kb = squid.ai().knowledgeBase('product-docs');
390
+
391
+ // Get knowledge base details
392
+ const kbDetails = await kb.getKnowledgeBase();
393
+ console.log(kbDetails);
394
+
395
+ // Create or update knowledge base
396
+ await kb.upsertKnowledgeBase({
397
+ description: 'Product documentation knowledge base',
398
+ // ...other options
399
+ });
400
+
401
+ // Delete knowledge base
402
+ await kb.delete();
403
+
404
+ // List all knowledge bases
405
+ const allKBs = await squid.ai().listKnowledgeBases();
406
+
407
+ // Upsert context (with or without file)
408
+ await kb.upsertContext({
409
+ contextId: 'doc-123',
410
+ text: 'Product documentation...',
411
+ metadata: { category: 'user-guide', version: '2.0' }
412
+ }, optionalFile);
413
+
414
+ // Batch upsert
415
+ await kb.upsertContexts([
416
+ { contextId: 'doc-1', text: '...' },
417
+ { contextId: 'doc-2', text: '...' }
418
+ ], optionalFiles);
419
+
420
+ // Search with prompt
421
+ const results = await kb.searchContextsWithPrompt({
422
+ prompt: 'How do I reset password?',
423
+ limit: 5,
424
+ metadata: { category: 'user-guide' }
425
+ });
426
+
427
+ // Search by context ID
428
+ const related = await kb.searchContextsWithContextId({
429
+ contextId: 'doc-123',
430
+ limit: 10
431
+ });
432
+
433
+ // Semantic search (returns chunks)
434
+ const searchResults = await kb.search({
435
+ prompt: 'authentication',
436
+ limit: 10
437
+ });
438
+
439
+ // Get context
440
+ const context = await kb.getContext('doc-123');
441
+
442
+ // List contexts
443
+ const allContexts = await kb.listContexts(1000); // truncateTextAfter
444
+ const contextIds = await kb.listContextIds();
445
+
446
+ // Download context
447
+ const download = await kb.downloadContext('doc-123');
448
+
449
+ // Delete contexts
450
+ await kb.deleteContext('doc-123');
451
+ await kb.deleteContexts(['doc-1', 'doc-2']);
452
+ ```
453
+
454
+ ## AI Files
455
+
456
+ Manage files stored with AI providers (OpenAI, etc.) for use with agents.
457
+
458
+ ```typescript
459
+ const aiFiles = squid.ai().files('openai'); // provider: 'openai' | 'anthropic' | etc.
460
+
461
+ // Upload file to AI provider
462
+ const fileId = await aiFiles.uploadFile({
463
+ file: myFile, // Browser File object
464
+ purpose: 'assistants'
465
+ });
466
+ console.log('Uploaded file ID:', fileId);
467
+
468
+ // Delete file from AI provider
469
+ const deleted = await aiFiles.deleteFile(fileId);
470
+ console.log('File deleted:', deleted);
471
+ ```
472
+
473
+ ## Image & Audio
474
+
475
+ REST API: [AI Image API](https://docs.getsquid.ai/reference-docs/api/#tag/AI-Image), [AI Audio API](https://docs.getsquid.ai/reference-docs/api/#tag/AI-Audio) | OpenAI-specific: [openai.md](openai.md)
476
+
477
+ ### Image Generation
478
+
479
+ ```typescript
480
+ // Generate image
481
+ const imageUrl = await squid.ai().image().generate(
482
+ 'A futuristic city',
483
+ { size: '1024x1024', quality: 'hd' }
484
+ );
485
+
486
+ // Remove background
487
+ const noBgBase64 = await squid.ai().image().removeBackground(imageFile);
488
+ ```
489
+
490
+ ### Audio Processing
491
+
492
+ ```typescript
493
+ // Transcribe audio
494
+ const text = await squid.ai().audio().transcribe(audioFile, {
495
+ language: 'en'
496
+ });
497
+
498
+ // Text-to-speech
499
+ const audioFile = await squid.ai().audio().createSpeech(
500
+ 'Hello world',
501
+ { modelName: 'tts-1', voice: 'alloy', speed: 1.0 }
502
+ );
503
+ ```
504
+
505
+ ## AI Query & API Call
506
+
507
+ AI Query allows you to query your database using natural language prompts. REST API: [Database API](https://docs.getsquid.ai/reference-docs/api/#tag/Database)
508
+
509
+ ```typescript
510
+ // Natural language database query (basic)
511
+ const result = await squid.ai().executeAiQuery(
512
+ 'built_in_db',
513
+ 'Show me all active users who registered last month'
514
+ );
515
+
516
+ // With options
517
+ const result = await squid.ai().executeAiQuery(
518
+ 'built_in_db',
519
+ 'Show me all active users who registered last month',
520
+ {
521
+ instructions: 'Only query the users collection',
522
+ enableRawResults: true,
523
+ selectCollectionsOptions: {
524
+ collectionsToUse: ['users']
525
+ },
526
+ generateQueryOptions: {
527
+ maxErrorCorrections: 3
528
+ },
529
+ analyzeResultsOptions: {
530
+ enableCodeInterpreter: true
531
+ }
532
+ }
533
+ );
534
+
535
+ // AI-powered API call
536
+ const apiResult = await squid.ai().executeAiApiCall(
537
+ 'stripe-api',
538
+ 'Create a $50 charge for customer cus_123',
539
+ ['create-charge'], // allowed endpoints
540
+ true // provide explanation
541
+ );
542
+ ```
543
+
544
+ ## Application Settings
545
+
546
+ Manage AI provider settings and API keys for your application.
547
+
548
+ ```typescript
549
+ const aiClient = squid.ai();
550
+
551
+ // Get application AI settings
552
+ const settings = await aiClient.getApplicationAiSettings();
553
+
554
+ // Set application AI settings
555
+ await aiClient.setApplicationAiSettings({
556
+ defaultModel: 'gpt-5-mini',
557
+ // ... other settings
558
+ });
559
+
560
+ // Set AI provider API key secret
561
+ await aiClient.setAiProviderApiKeySecret(
562
+ 'openai', // providerType
563
+ 'OPENAI_API_KEY' // secret key name
564
+ );
565
+ ```
566
+
567
+ ## Backend Decorators
568
+
569
+ ### @aiFunction
570
+
571
+ Exposes function to AI agents. Agents automatically call these functions based on user prompts.
572
+
573
+ ```typescript
574
+ // Simple form: description and params array
575
+ @aiFunction('Returns the names of the pirates crew on a given ship name', [
576
+ { name: 'shipName', type: 'string', required: true, description: 'The name of the ship' }
577
+ ])
578
+ async getShipCrew({ shipName }: { shipName: string }): Promise<string[]> {
579
+ const crew = await getCrew(shipName);
580
+ return crew.map(m => m.name);
581
+ }
582
+
583
+ // Options object form with more control
584
+ @aiFunction({
585
+ id: 'custom-function-id',
586
+ description: 'Get user profile',
587
+ params: [
588
+ { name: 'userId', type: 'string', required: true, description: 'User ID' }
589
+ ],
590
+ attributes: {
591
+ integrationType: ['salesforce']
592
+ }
593
+ })
594
+ async getUserProfile(
595
+ params: { userId: string },
596
+ context: AiFunctionCallContext
597
+ ): Promise<User> {
598
+ console.log('Agent ID:', context.agentId);
599
+ console.log('Agent context:', context.agentContext);
600
+ console.log('Function context:', context.functionContext);
601
+ return { userId: params.userId, name: 'John' };
602
+ }
603
+
604
+ // Parameter types: 'string' | 'number' | 'boolean' | 'date' | 'files'
605
+ @aiFunction('Books a hotel room', [
606
+ { name: 'hotelName', type: 'string', required: true, description: 'Name of hotel' },
607
+ { name: 'checkInDate', type: 'date', required: true, description: 'Check-in date' },
608
+ { name: 'numberOfGuests', type: 'number', required: true, description: 'Number of guests' },
609
+ { name: 'breakfast', type: 'boolean', required: false, description: 'Include breakfast' },
610
+ { name: 'roomType', type: 'string', required: true, description: 'Type of room',
611
+ enum: ['single', 'double', 'suite'] }
612
+ ])
613
+ async bookHotel(args: BookingArgs): Promise<string> {
614
+ return `Booked ${args.roomType} room at ${args.hotelName}`;
615
+ }
616
+ ```
617
+
618
+ ### AI Security Decorators
619
+
620
+ For `@secureAiAgent` and `@secureAiQuery`, see [security.md](security.md#ai-security).
621
+
622
+ ## MCP (Model Context Protocol)
623
+
624
+ Squid supports MCP for extending agent capabilities.
625
+
626
+ ### @mcpServer
627
+
628
+ Define an MCP server that agents can connect to. The decorator is a class decorator.
629
+
630
+ ```typescript
631
+ @mcpServer({
632
+ id: 'my-mcp-server',
633
+ name: 'My MCP Server',
634
+ description: 'A server that provides custom tools',
635
+ version: '1.0.0'
636
+ })
637
+ export class MyMcpServer extends SquidService {
638
+ // MCP tools defined here
639
+ }
640
+ ```
641
+
642
+ **McpServerOptions:**
643
+ - `id` (string): Unique ID for this MCP server (used in MCP URL)
644
+ - `name` (string): The MCP name exposed in the manifest
645
+ - `description` (string): Description of the MCP server
646
+ - `version` (string): Version of the MCP server
647
+
648
+ ### @mcpTool
649
+
650
+ Define tools that MCP-connected agents can use. Takes an options object with description and inputSchema (JSON Schema).
651
+
652
+ ```typescript
653
+ @mcpTool({
654
+ description: 'Searches the database for records matching the query',
655
+ inputSchema: {
656
+ type: 'object',
657
+ properties: {
658
+ query: { type: 'string', description: 'Search query' },
659
+ limit: { type: 'number', description: 'Max results to return' }
660
+ },
661
+ required: ['query']
662
+ }
663
+ })
664
+ async searchDatabase({ query, limit = 10 }: { query: string; limit?: number }): Promise<SearchResults> {
665
+ return await this.squid.collection('records')
666
+ .query()
667
+ .like('content', `%${query}%`)
668
+ .limit(limit)
669
+ .snapshot();
670
+ }
671
+ ```
672
+
673
+ **McpToolMetadataOptions:**
674
+ - `description` (string): Describes the tool's capabilities (used by AI to determine when to call it)
675
+ - `inputSchema` (JSONSchema): Parameters for the MCP tool
676
+ - `outputSchema?` (JSONSchema): Optional output schema
677
+
678
+ ### @mcpAuthorizer
679
+
680
+ Authorize MCP connections. This decorator takes no arguments and is applied within an MCP server class.
681
+
682
+ ```typescript
683
+ @mcpAuthorizer()
684
+ authorizeMcp(): boolean {
685
+ return this.isAuthenticated();
686
+ }
687
+ ```
688
+
689
+ ## LLM Services
690
+
691
+ For custom LLM integrations. LLM services allow you to integrate custom AI models with Squid's AI infrastructure.
692
+
693
+ ### @llmService
694
+
695
+ Define a custom LLM service. This is a class decorator that registers custom AI models.
696
+
697
+ ```typescript
698
+ import { llmService, llmAsk, SquidLlmService } from '@squidcloud/backend';
699
+
700
+ const MY_MODELS = {
701
+ 'my-model-v1': { displayName: 'My Model v1', maxTokens: 4096 },
702
+ 'my-model-v2': { displayName: 'My Model v2', maxTokens: 8192 }
703
+ };
704
+
705
+ @llmService({ models: MY_MODELS, supportsFunctions: true })
706
+ export class CustomLlmService extends SquidLlmService {
707
+ @llmAsk()
708
+ async ask(prompt: string): Promise<string> {
709
+ // Custom LLM implementation
710
+ const response = await callMyCustomLlm(prompt);
711
+ return response;
712
+ }
713
+ }
714
+ ```
715
+
716
+ **LlmServiceOptions:**
717
+ - `models` (Record<string, ModelMetadata>): Map of model names to their metadata
718
+ - `supportsFunctions?` (boolean): Whether the LLM supports function calling
719
+
720
+ **Note:** Custom LLM services extend `SquidLlmService`, not `SquidService`.
721
+
722
+ ## AI Functions Configurator
723
+
724
+ Configure which AI functions are available to agents for specific integration types. This allows you to override or exclude functions and set predefined parameters.
725
+
726
+ ```typescript
727
+ import { aiFunctionsConfigurator, AiFunctionsConfiguratorRequest, AiFunctionsConfiguratorResponse } from '@squidcloud/backend';
728
+
729
+ @aiFunctionsConfigurator({ integrationTypes: ['salesforce', 'hubspot'] })
730
+ configureAiFunctions(request: AiFunctionsConfiguratorRequest): AiFunctionsConfiguratorResponse {
731
+ console.log('Integration ID:', request.integrationId);
732
+ console.log('Integration type:', request.integrationType);
733
+
734
+ return {
735
+ functionOverrides: {
736
+ 'getInventory': {
737
+ id: 'getInventory',
738
+ isExcluded: false,
739
+ predefinedParameters: { region: 'us-west-2' }
740
+ },
741
+ 'processPayment': {
742
+ id: 'processPayment',
743
+ isExcluded: !this.isAuthenticated(),
744
+ predefinedParameters: {}
745
+ }
746
+ }
747
+ };
748
+ }
749
+ ```
750
+
751
+ **AiFunctionsConfiguratorMetadataOptions:**
752
+ - `id?` (string): Unique configurator ID (defaults to function name)
753
+ - `integrationTypes` (IntegrationType[]): Integration types this configurator applies to
754
+
755
+ **AiFunctionsConfiguratorRequest:**
756
+ - `integrationId`: ID of the connected integration
757
+ - `integrationType`: Type of the integration
758
+ - `metadata`: Current connected integration metadata
759
+
760
+ **AiFunctionsConfiguratorResponse:**
761
+ - `functionOverrides`: Map of function ID to override details
762
+ - `id`: Function ID
763
+ - `isExcluded?`: If true, function won't be available
764
+ - `predefinedParameters`: Parameters to fill with predefined values
765
+
766
+ ## Best Practices
767
+
768
+ 1. **Use memoryOptions for AI conversations** - Not deprecated chatId
769
+ 2. **Agent IDs are permanent** - Plan naming carefully, cannot be changed after creation
770
+ 3. **Memory is enabled by default** - Set `memoryMode: 'none'` to disable conversation history
771
+ 4. **Streaming behavior differs with connected resources** - No resources: streams token-by-token; Has resources: emits once with complete response
772
+ 5. **Deleting an agent doesn't delete chat history** - History persists independently
773
+ 6. **Custom LLM services extend SquidLlmService** - Not SquidService