squidcloud
Squid Cloud Python client SDK.
Usage::
from squidcloud import Squid
squid = Squid(
app_id="my-app",
api_key="my-api-key",
region="us-east-1.aws",
environment_id="dev",
)
# AI agents
response = await squid.ai().agent("my-agent").ask("Hello!")
# Execute backend function
result = await squid.execute_function("MyService:greet", "World")
# Web utilities
content = await squid.web().get_url_content("https://example.com")
1"""Squid Cloud Python client SDK. 2 3Usage:: 4 5 from squidcloud import Squid 6 7 squid = Squid( 8 app_id="my-app", 9 api_key="my-api-key", 10 region="us-east-1.aws", 11 environment_id="dev", 12 ) 13 14 # AI agents 15 response = await squid.ai().agent("my-agent").ask("Hello!") 16 17 # Execute backend function 18 result = await squid.execute_function("MyService:greet", "World") 19 20 # Web utilities 21 content = await squid.web().get_url_content("https://example.com") 22""" 23 24from squidcloud.ai import ( 25 AgentClient, 26 AiClient, 27 AudioClient, 28 ImageClient, 29 KnowledgeBaseClient, 30) 31from squidcloud.client import Squid 32from squidcloud.extraction import ExtractionClient 33from squidcloud.http import SquidHttpError 34from squidcloud.matchmaking import MatchmakingClient 35from squidcloud.types import ( 36 AiAgent, 37 AiAgentExecutionPlanOptions, 38 AiAgentMcpServerConfig, 39 AiAgentMemoryOptions, 40 AiAgentResponseFormat, 41 AiAudioCreateSpeechOptions, 42 AiChatModelSelection, 43 AiChatOptions, 44 AiChatPromptQuotas, 45 AiConnectedAgentMetadata, 46 AiConnectedIntegrationMetadata, 47 AiConnectedKnowledgeBaseMetadata, 48 AiContextFileOptions, 49 AiContextTextOptions, 50 AiEmbeddingsModelSelection, 51 AiFileUrl, 52 AiFunctionAttributes, 53 AiFunctionMetadata, 54 AiFunctionParam, 55 AiKnowledgeBase, 56 AiKnowledgeBaseGraphConceptsConfig, 57 AiKnowledgeBaseGraphConfig, 58 AiKnowledgeBaseGraphFilter, 59 AiKnowledgeBaseGraphPathFacetConfig, 60 AiKnowledgeBaseGraphSearchOptions, 61 AiKnowledgeBaseMetadataField, 62 AiPiiOptions, 63 AiQueryAnalyzeResultsOptions, 64 AiQueryCollectionsSelectionRunMode, 65 AiQueryGenerateQueryOptions, 66 AiQueryOptions, 67 AiQuerySelectCollectionsOptions, 68 AiQueryValidateWithAiOptions, 69 AiSessionContext, 70 AiStructuredOutputFormat, 71 ContextRequest, 72 CreatePdfDimensionsOptions, 73 CreatePdfFormatOptions, 74 CreatePdfOutputOptions, 75 ExtractDataFromDocumentOptions, 76 FileContextRequest, 77 FluxOptions, 78 GptImageOptions, 79 GuardrailsOptions, 80 ImageGenerateOptions, 81 IntegrationEmbeddingModelSpec, 82 IntegrationModelSpec, 83 KnowledgeBaseGraphQueryOp, 84 KnowledgeBaseSearchOptions, 85 MmCategory, 86 MmEntity, 87 MmFindMatchesOptions, 88 MmListEntitiesOptions, 89 ModelIdSpec, 90 StableDiffusionOptions, 91 TextContextRequest, 92 UpsertAgentOptions, 93 VectorDbType, 94 WebAiSearchResponse, 95 WebShortUrlBulkResponse, 96 WebShortUrlResponse, 97) 98from squidcloud.web import WebClient 99 100__all__ = [ 101 "AgentClient", 102 "AiAgent", 103 "AiAgentExecutionPlanOptions", 104 "AiAgentMcpServerConfig", 105 "AiAgentMemoryOptions", 106 "AiAgentResponseFormat", 107 "AiAudioCreateSpeechOptions", 108 "AiChatModelSelection", 109 # AI Chat 110 "AiChatOptions", 111 "AiChatPromptQuotas", 112 "AiClient", 113 "AiConnectedAgentMetadata", 114 "AiConnectedIntegrationMetadata", 115 "AiConnectedKnowledgeBaseMetadata", 116 "AiContextFileOptions", 117 "AiContextTextOptions", 118 "AiEmbeddingsModelSelection", 119 "AiFileUrl", 120 "AiFunctionAttributes", 121 "AiFunctionMetadata", 122 "AiFunctionParam", 123 # Knowledge Base 124 "AiKnowledgeBase", 125 "AiKnowledgeBaseGraphConceptsConfig", 126 "AiKnowledgeBaseGraphConfig", 127 "AiKnowledgeBaseGraphFilter", 128 "AiKnowledgeBaseGraphPathFacetConfig", 129 "AiKnowledgeBaseGraphSearchOptions", 130 "AiKnowledgeBaseMetadataField", 131 "AiPiiOptions", 132 # AI Query 133 "AiQueryAnalyzeResultsOptions", 134 "AiQueryCollectionsSelectionRunMode", 135 "AiQueryGenerateQueryOptions", 136 "AiQueryOptions", 137 "AiQuerySelectCollectionsOptions", 138 "AiQueryValidateWithAiOptions", 139 "AiSessionContext", 140 "AiStructuredOutputFormat", 141 "AudioClient", 142 "ContextRequest", 143 "CreatePdfDimensionsOptions", 144 "CreatePdfFormatOptions", 145 # Extraction 146 "CreatePdfOutputOptions", 147 "ExtractDataFromDocumentOptions", 148 "ExtractionClient", 149 "FileContextRequest", 150 "FluxOptions", 151 "GptImageOptions", 152 "GuardrailsOptions", 153 # Image 154 "ImageClient", 155 "ImageGenerateOptions", 156 "IntegrationEmbeddingModelSpec", 157 "IntegrationModelSpec", 158 "KnowledgeBaseClient", 159 "KnowledgeBaseGraphQueryOp", 160 "KnowledgeBaseSearchOptions", 161 # Matchmaking 162 "MatchmakingClient", 163 "MmCategory", 164 "MmEntity", 165 "MmFindMatchesOptions", 166 "MmListEntitiesOptions", 167 "ModelIdSpec", 168 "Squid", 169 "SquidHttpError", 170 "StableDiffusionOptions", 171 "TextContextRequest", 172 "UpsertAgentOptions", 173 "VectorDbType", 174 # Web 175 "WebAiSearchResponse", 176 "WebClient", 177 "WebShortUrlBulkResponse", 178 "WebShortUrlResponse", 179]
146class AgentClient: 147 """Operations on a single AI agent. 148 149 Provides methods for chatting with an agent, managing its configuration, 150 updating guardrails, and working with revisions. 151 152 Obtained via :meth:`AiClient.agent`. 153 154 Example:: 155 156 agent = squid.ai().agent("my-agent") 157 response = await agent.ask("What is the weather?", options={"temperature": 0.7}) 158 await agent.update_instructions("Always respond in haiku format.") 159 """ 160 161 def __init__(self, http: HttpTransport, agent_id: str) -> None: 162 self._http = http 163 self._agent_id = agent_id 164 165 # --- Chat --- 166 167 async def ask( 168 self, 169 prompt: str, 170 options: AiChatOptions | None = None, 171 ) -> str: 172 """Ask the agent a question and get a text response. 173 174 Args: 175 prompt: The user's question or instruction. 176 options: Chat options controlling model, temperature, memory, 177 functions, guardrails, and more. See :class:`AiChatOptions`. 178 179 Returns: 180 The agent's response as a string. 181 182 Raises: 183 SquidHttpError: If the agent is not found or the request fails. 184 185 Example:: 186 187 response = await agent.ask( 188 "Summarize this document", 189 options={ 190 "model": "gemini-3-flash", 191 "temperature": 0.3, 192 "memoryOptions": {"memoryId": "session-1", "memoryMode": "read-write"}, 193 }, 194 ) 195 """ 196 result = await self._http.post( 197 "squid-api/v1/ai/agent/ask", 198 {"agentId": self._agent_id, "prompt": prompt, "options": options or {}}, 199 ) 200 return result.get("responseString", "") if result else "" 201 202 async def ask_with_annotations( 203 self, 204 prompt: str, 205 options: AiChatOptions | None = None, 206 ) -> dict: 207 """Ask the agent and get a response with annotations. 208 209 Annotations include file references, citations, and other metadata 210 the agent may attach to its response. 211 212 Args: 213 prompt: The user's question or instruction. 214 options: Chat options. See :class:`AiChatOptions`. 215 216 Returns: 217 A dict with: 218 - ``responseString`` (str): The text response. 219 - ``annotations`` (dict): Annotation metadata keyed by ID. 220 221 Example:: 222 223 result = await agent.ask_with_annotations("Find relevant docs") 224 print(result["responseString"]) 225 for ann_id, ann in result.get("annotations", {}).items(): 226 print(f" Annotation: {ann}") 227 """ 228 return await self._http.post( 229 "squid-api/v1/ai/agent/askWithAnnotations", 230 {"agentId": self._agent_id, "prompt": prompt, "options": options or {}}, 231 ) 232 233 # --- Management --- 234 235 async def get(self) -> dict | None: 236 """Get the agent's configuration. 237 238 Returns: 239 An ``AiAgent`` dict with keys: ``id``, ``createdAt``, ``updatedAt``, 240 ``description``, ``isPublic``, ``auditLog``, ``auditLogFullContext``, 241 ``options``, ``apiKey``. 242 Returns ``None`` if the agent does not exist. 243 """ 244 return await self._http.get(f"squid-api/v1/ai/agent/get/{self._agent_id}") 245 246 async def upsert( 247 self, 248 *, 249 description: str | None = None, 250 is_public: bool | None = None, 251 audit_log: bool | None = None, 252 audit_log_full_context: bool | None = None, 253 api_key: str | None = None, 254 mcp_server: AiAgentMcpServerConfig | None = None, 255 options: AiChatOptions | None = None, 256 ) -> None: 257 """Create or update the agent. 258 259 If the agent does not exist, it is created. If it exists, the provided 260 fields are updated (fields set to ``None`` are left unchanged). 261 262 Args: 263 description: A description of the agent's purpose or capabilities. 264 is_public: Whether the agent is publicly accessible (default ``False``). 265 audit_log: Enable audit logging for the agent's activities. 266 audit_log_full_context: Record the full agent context (system 267 instructions and retrieved knowledge-base content) in the audit 268 log; requires ``audit_log``. 269 api_key: Optional API key used specifically for this agent. 270 mcp_server: Configuration for exposing the agent as an MCP server 271 at ``/mcp/<agentId>``. See :class:`AiAgentMcpServerConfig`. 272 options: Default chat options applied to every request unless 273 overridden per-call. See :class:`AiChatOptions`. 274 275 Example:: 276 277 await agent.upsert( 278 description="Customer support agent", 279 options={"model": "gemini-3-flash", "temperature": 0.5}, 280 ) 281 """ 282 body: dict[str, Any] = {"id": self._agent_id} 283 if description is not None: 284 body["description"] = description 285 if is_public is not None: 286 body["isPublic"] = is_public 287 if audit_log is not None: 288 body["auditLog"] = audit_log 289 if audit_log_full_context is not None: 290 body["auditLogFullContext"] = audit_log_full_context 291 if api_key is not None: 292 body["apiKey"] = api_key 293 if mcp_server is not None: 294 body["mcpServer"] = mcp_server 295 if options is not None: 296 body["options"] = options 297 await self._http.post("squid-api/v1/ai/agent/upsert", body) 298 299 async def delete(self) -> None: 300 """Delete the agent permanently.""" 301 await self._http.post("squid-api/v1/ai/agent/delete", {"agentId": self._agent_id}) 302 303 async def update_instructions(self, instructions: str) -> None: 304 """Update the agent's system instructions. 305 306 Args: 307 instructions: The new system prompt / instructions text. 308 """ 309 await self._http.post( 310 "squid-api/v1/ai/agent/updateInstructions", 311 {"agentId": self._agent_id, "instructions": instructions}, 312 ) 313 314 async def update_model(self, model: AiChatModelSelection) -> None: 315 """Update the agent's default LLM model. 316 317 Args: 318 model: A model name string (e.g., ``'gemini-3-flash'``) or an 319 ``IntegrationModelSpec`` dict (``{'integrationId': str, 'model': str}``). 320 """ 321 await self._http.post( 322 "squid-api/v1/ai/agent/updateModel", 323 {"agentId": self._agent_id, "model": model}, 324 ) 325 326 async def update_connected_agents( 327 self, connected_agents: list[AiConnectedAgentMetadata] 328 ) -> None: 329 """Update the list of connected agents. 330 331 Connected agents can be called by this agent during conversations. 332 333 Args: 334 connected_agents: List of ``{'agentId': str, 'description': str}`` dicts. 335 """ 336 await self._http.post( 337 "squid-api/v1/ai/agent/updateConnectedAgents", 338 {"agentId": self._agent_id, "connectedAgents": connected_agents}, 339 ) 340 341 async def update_guardrails(self, guardrails: GuardrailsOptions) -> None: 342 """Update the agent's guardrail settings. 343 344 Args: 345 guardrails: A :class:`GuardrailsOptions` dict with optional keys: 346 ``custom``, ``disablePii``, ``professionalTone``, 347 ``offTopicAnswers``, ``disableProfanity``. 348 349 Example:: 350 351 await agent.update_guardrails( 352 { 353 "professionalTone": True, 354 "disableProfanity": True, 355 } 356 ) 357 """ 358 await self._http.post( 359 "squid-api/v1/ai/agent/updateGuardrails", 360 {"agentId": self._agent_id, "guardrails": guardrails}, 361 ) 362 363 async def update_custom_guardrails(self, custom_guardrail: str) -> None: 364 """Update the custom guardrail instruction text. 365 366 Args: 367 custom_guardrail: Free-form guardrail instruction string. 368 """ 369 await self._http.post( 370 "squid-api/v1/ai/agent/updateCustomGuardrails", 371 {"agentId": self._agent_id, "customGuardrail": custom_guardrail}, 372 ) 373 374 async def delete_custom_guardrails(self) -> None: 375 """Delete the custom guardrail, reverting to defaults.""" 376 await self._http.post( 377 "squid-api/v1/ai/agent/deleteCustomGuardrails", 378 {"agentId": self._agent_id}, 379 ) 380 381 async def update_pii(self, pii: AiPiiOptions) -> None: 382 """Update the agent's PII screening, merging with its existing settings. 383 384 With ``onDetect`` set to ``"reject"`` the agent refuses any prompt carrying 385 PII before it reaches the model, so the prompt is never answered and never 386 stored. This is the inverse of ``GuardrailsOptions.disablePii``, which asks 387 the agent's own model not to emit PII in its answer. 388 389 Args: 390 pii: An :class:`AiPiiOptions` dict with optional keys: ``onDetect``, 391 ``entities``, ``customRules``, ``classifierModel``, ``allowList``. 392 393 Example:: 394 395 await agent.update_pii( 396 { 397 "onDetect": "reject", 398 "customRules": ["internal case numbers like CASE-12345"], 399 } 400 ) 401 """ 402 agent = await self.get() 403 existing = (agent or {}).get("options", {}).get("pii", {}) 404 merged = {"onDetect": "off", **existing, **pii} 405 await self._http.post( 406 "squid-api/v1/ai/agent/setAgentOptionInPath", 407 {"agentId": self._agent_id, "path": "pii", "value": merged}, 408 ) 409 410 # --- Revisions --- 411 412 async def list_revisions(self) -> list[dict]: 413 """List all revisions of this agent. 414 415 Returns: 416 A list of ``AiAgentRevision`` dicts, each containing: 417 ``agentId``, ``revisionNumber``, ``action``, ``createdAt``, 418 ``agentSnapshot``. 419 """ 420 result = await self._http.get(f"squid-api/v1/ai/agent/revisions/{self._agent_id}") 421 return result.get("revisions", []) if result else [] 422 423 async def restore_revision(self, revision_number: int) -> None: 424 """Restore the agent to a previous revision. 425 426 Args: 427 revision_number: The revision number to restore. 428 """ 429 await self._http.post( 430 "squid-api/v1/ai/agent/restoreRevision", 431 {"agentId": self._agent_id, "revisionNumber": revision_number}, 432 ) 433 434 async def delete_revision(self, revision_number: int) -> None: 435 """Delete a specific revision. 436 437 Args: 438 revision_number: The revision number to delete. 439 """ 440 await self._http.post( 441 "squid-api/v1/ai/agent/deleteRevision", 442 {"agentId": self._agent_id, "revisionNumber": revision_number}, 443 )
Operations on a single AI agent.
Provides methods for chatting with an agent, managing its configuration, updating guardrails, and working with revisions.
Obtained via AiClient.agent().
Example::
agent = squid.ai().agent("my-agent")
response = await agent.ask("What is the weather?", options={"temperature": 0.7})
await agent.update_instructions("Always respond in haiku format.")
167 async def ask( 168 self, 169 prompt: str, 170 options: AiChatOptions | None = None, 171 ) -> str: 172 """Ask the agent a question and get a text response. 173 174 Args: 175 prompt: The user's question or instruction. 176 options: Chat options controlling model, temperature, memory, 177 functions, guardrails, and more. See :class:`AiChatOptions`. 178 179 Returns: 180 The agent's response as a string. 181 182 Raises: 183 SquidHttpError: If the agent is not found or the request fails. 184 185 Example:: 186 187 response = await agent.ask( 188 "Summarize this document", 189 options={ 190 "model": "gemini-3-flash", 191 "temperature": 0.3, 192 "memoryOptions": {"memoryId": "session-1", "memoryMode": "read-write"}, 193 }, 194 ) 195 """ 196 result = await self._http.post( 197 "squid-api/v1/ai/agent/ask", 198 {"agentId": self._agent_id, "prompt": prompt, "options": options or {}}, 199 ) 200 return result.get("responseString", "") if result else ""
Ask the agent a question and get a text response.
Arguments:
- prompt: The user's question or instruction.
- options: Chat options controlling model, temperature, memory,
functions, guardrails, and more. See
AiChatOptions.
Returns:
The agent's response as a string.
Raises:
- SquidHttpError: If the agent is not found or the request fails.
Example::
response = await agent.ask(
"Summarize this document",
options={
"model": "gemini-3-flash",
"temperature": 0.3,
"memoryOptions": {"memoryId": "session-1", "memoryMode": "read-write"},
},
)
202 async def ask_with_annotations( 203 self, 204 prompt: str, 205 options: AiChatOptions | None = None, 206 ) -> dict: 207 """Ask the agent and get a response with annotations. 208 209 Annotations include file references, citations, and other metadata 210 the agent may attach to its response. 211 212 Args: 213 prompt: The user's question or instruction. 214 options: Chat options. See :class:`AiChatOptions`. 215 216 Returns: 217 A dict with: 218 - ``responseString`` (str): The text response. 219 - ``annotations`` (dict): Annotation metadata keyed by ID. 220 221 Example:: 222 223 result = await agent.ask_with_annotations("Find relevant docs") 224 print(result["responseString"]) 225 for ann_id, ann in result.get("annotations", {}).items(): 226 print(f" Annotation: {ann}") 227 """ 228 return await self._http.post( 229 "squid-api/v1/ai/agent/askWithAnnotations", 230 {"agentId": self._agent_id, "prompt": prompt, "options": options or {}}, 231 )
Ask the agent and get a response with annotations.
Annotations include file references, citations, and other metadata the agent may attach to its response.
Arguments:
- prompt: The user's question or instruction.
- options: Chat options. See
AiChatOptions.
Returns:
A dict with: -
responseString(str): The text response. -annotations(dict): Annotation metadata keyed by ID.
Example::
result = await agent.ask_with_annotations("Find relevant docs")
print(result["responseString"])
for ann_id, ann in result.get("annotations", {}).items():
print(f" Annotation: {ann}")
235 async def get(self) -> dict | None: 236 """Get the agent's configuration. 237 238 Returns: 239 An ``AiAgent`` dict with keys: ``id``, ``createdAt``, ``updatedAt``, 240 ``description``, ``isPublic``, ``auditLog``, ``auditLogFullContext``, 241 ``options``, ``apiKey``. 242 Returns ``None`` if the agent does not exist. 243 """ 244 return await self._http.get(f"squid-api/v1/ai/agent/get/{self._agent_id}")
Get the agent's configuration.
Returns:
An
AiAgentdict with keys:id,createdAt,updatedAt,description,isPublic,auditLog,auditLogFullContext,options,apiKey. ReturnsNoneif the agent does not exist.
246 async def upsert( 247 self, 248 *, 249 description: str | None = None, 250 is_public: bool | None = None, 251 audit_log: bool | None = None, 252 audit_log_full_context: bool | None = None, 253 api_key: str | None = None, 254 mcp_server: AiAgentMcpServerConfig | None = None, 255 options: AiChatOptions | None = None, 256 ) -> None: 257 """Create or update the agent. 258 259 If the agent does not exist, it is created. If it exists, the provided 260 fields are updated (fields set to ``None`` are left unchanged). 261 262 Args: 263 description: A description of the agent's purpose or capabilities. 264 is_public: Whether the agent is publicly accessible (default ``False``). 265 audit_log: Enable audit logging for the agent's activities. 266 audit_log_full_context: Record the full agent context (system 267 instructions and retrieved knowledge-base content) in the audit 268 log; requires ``audit_log``. 269 api_key: Optional API key used specifically for this agent. 270 mcp_server: Configuration for exposing the agent as an MCP server 271 at ``/mcp/<agentId>``. See :class:`AiAgentMcpServerConfig`. 272 options: Default chat options applied to every request unless 273 overridden per-call. See :class:`AiChatOptions`. 274 275 Example:: 276 277 await agent.upsert( 278 description="Customer support agent", 279 options={"model": "gemini-3-flash", "temperature": 0.5}, 280 ) 281 """ 282 body: dict[str, Any] = {"id": self._agent_id} 283 if description is not None: 284 body["description"] = description 285 if is_public is not None: 286 body["isPublic"] = is_public 287 if audit_log is not None: 288 body["auditLog"] = audit_log 289 if audit_log_full_context is not None: 290 body["auditLogFullContext"] = audit_log_full_context 291 if api_key is not None: 292 body["apiKey"] = api_key 293 if mcp_server is not None: 294 body["mcpServer"] = mcp_server 295 if options is not None: 296 body["options"] = options 297 await self._http.post("squid-api/v1/ai/agent/upsert", body)
Create or update the agent.
If the agent does not exist, it is created. If it exists, the provided
fields are updated (fields set to None are left unchanged).
Arguments:
- description: A description of the agent's purpose or capabilities.
- is_public: Whether the agent is publicly accessible (default
False). - audit_log: Enable audit logging for the agent's activities.
- audit_log_full_context: Record the full agent context (system
instructions and retrieved knowledge-base content) in the audit
log; requires
audit_log. - api_key: Optional API key used specifically for this agent.
- mcp_server: Configuration for exposing the agent as an MCP server
at
/mcp/<agentId>. SeeAiAgentMcpServerConfig. - options: Default chat options applied to every request unless
overridden per-call. See
AiChatOptions.
Example::
await agent.upsert(
description="Customer support agent",
options={"model": "gemini-3-flash", "temperature": 0.5},
)
299 async def delete(self) -> None: 300 """Delete the agent permanently.""" 301 await self._http.post("squid-api/v1/ai/agent/delete", {"agentId": self._agent_id})
Delete the agent permanently.
303 async def update_instructions(self, instructions: str) -> None: 304 """Update the agent's system instructions. 305 306 Args: 307 instructions: The new system prompt / instructions text. 308 """ 309 await self._http.post( 310 "squid-api/v1/ai/agent/updateInstructions", 311 {"agentId": self._agent_id, "instructions": instructions}, 312 )
Update the agent's system instructions.
Arguments:
- instructions: The new system prompt / instructions text.
314 async def update_model(self, model: AiChatModelSelection) -> None: 315 """Update the agent's default LLM model. 316 317 Args: 318 model: A model name string (e.g., ``'gemini-3-flash'``) or an 319 ``IntegrationModelSpec`` dict (``{'integrationId': str, 'model': str}``). 320 """ 321 await self._http.post( 322 "squid-api/v1/ai/agent/updateModel", 323 {"agentId": self._agent_id, "model": model}, 324 )
Update the agent's default LLM model.
Arguments:
- model: A model name string (e.g.,
'gemini-3-flash') or anIntegrationModelSpecdict ({'integrationId': str, 'model': str}).
326 async def update_connected_agents( 327 self, connected_agents: list[AiConnectedAgentMetadata] 328 ) -> None: 329 """Update the list of connected agents. 330 331 Connected agents can be called by this agent during conversations. 332 333 Args: 334 connected_agents: List of ``{'agentId': str, 'description': str}`` dicts. 335 """ 336 await self._http.post( 337 "squid-api/v1/ai/agent/updateConnectedAgents", 338 {"agentId": self._agent_id, "connectedAgents": connected_agents}, 339 )
Update the list of connected agents.
Connected agents can be called by this agent during conversations.
Arguments:
- connected_agents: List of
{'agentId': str, 'description': str}dicts.
341 async def update_guardrails(self, guardrails: GuardrailsOptions) -> None: 342 """Update the agent's guardrail settings. 343 344 Args: 345 guardrails: A :class:`GuardrailsOptions` dict with optional keys: 346 ``custom``, ``disablePii``, ``professionalTone``, 347 ``offTopicAnswers``, ``disableProfanity``. 348 349 Example:: 350 351 await agent.update_guardrails( 352 { 353 "professionalTone": True, 354 "disableProfanity": True, 355 } 356 ) 357 """ 358 await self._http.post( 359 "squid-api/v1/ai/agent/updateGuardrails", 360 {"agentId": self._agent_id, "guardrails": guardrails}, 361 )
Update the agent's guardrail settings.
Arguments:
- guardrails: A
GuardrailsOptionsdict with optional keys:custom,disablePii,professionalTone,offTopicAnswers,disableProfanity.
Example::
await agent.update_guardrails(
{
"professionalTone": True,
"disableProfanity": True,
}
)
363 async def update_custom_guardrails(self, custom_guardrail: str) -> None: 364 """Update the custom guardrail instruction text. 365 366 Args: 367 custom_guardrail: Free-form guardrail instruction string. 368 """ 369 await self._http.post( 370 "squid-api/v1/ai/agent/updateCustomGuardrails", 371 {"agentId": self._agent_id, "customGuardrail": custom_guardrail}, 372 )
Update the custom guardrail instruction text.
Arguments:
- custom_guardrail: Free-form guardrail instruction string.
374 async def delete_custom_guardrails(self) -> None: 375 """Delete the custom guardrail, reverting to defaults.""" 376 await self._http.post( 377 "squid-api/v1/ai/agent/deleteCustomGuardrails", 378 {"agentId": self._agent_id}, 379 )
Delete the custom guardrail, reverting to defaults.
381 async def update_pii(self, pii: AiPiiOptions) -> None: 382 """Update the agent's PII screening, merging with its existing settings. 383 384 With ``onDetect`` set to ``"reject"`` the agent refuses any prompt carrying 385 PII before it reaches the model, so the prompt is never answered and never 386 stored. This is the inverse of ``GuardrailsOptions.disablePii``, which asks 387 the agent's own model not to emit PII in its answer. 388 389 Args: 390 pii: An :class:`AiPiiOptions` dict with optional keys: ``onDetect``, 391 ``entities``, ``customRules``, ``classifierModel``, ``allowList``. 392 393 Example:: 394 395 await agent.update_pii( 396 { 397 "onDetect": "reject", 398 "customRules": ["internal case numbers like CASE-12345"], 399 } 400 ) 401 """ 402 agent = await self.get() 403 existing = (agent or {}).get("options", {}).get("pii", {}) 404 merged = {"onDetect": "off", **existing, **pii} 405 await self._http.post( 406 "squid-api/v1/ai/agent/setAgentOptionInPath", 407 {"agentId": self._agent_id, "path": "pii", "value": merged}, 408 )
Update the agent's PII screening, merging with its existing settings.
With onDetect set to "reject" the agent refuses any prompt carrying
PII before it reaches the model, so the prompt is never answered and never
stored. This is the inverse of GuardrailsOptions.disablePii, which asks
the agent's own model not to emit PII in its answer.
Arguments:
- pii: An
AiPiiOptionsdict with optional keys:onDetect,entities,customRules,classifierModel,allowList.
Example::
await agent.update_pii(
{
"onDetect": "reject",
"customRules": ["internal case numbers like CASE-12345"],
}
)
412 async def list_revisions(self) -> list[dict]: 413 """List all revisions of this agent. 414 415 Returns: 416 A list of ``AiAgentRevision`` dicts, each containing: 417 ``agentId``, ``revisionNumber``, ``action``, ``createdAt``, 418 ``agentSnapshot``. 419 """ 420 result = await self._http.get(f"squid-api/v1/ai/agent/revisions/{self._agent_id}") 421 return result.get("revisions", []) if result else []
List all revisions of this agent.
Returns:
A list of
AiAgentRevisiondicts, each containing:agentId,revisionNumber,action,createdAt,agentSnapshot.
423 async def restore_revision(self, revision_number: int) -> None: 424 """Restore the agent to a previous revision. 425 426 Args: 427 revision_number: The revision number to restore. 428 """ 429 await self._http.post( 430 "squid-api/v1/ai/agent/restoreRevision", 431 {"agentId": self._agent_id, "revisionNumber": revision_number}, 432 )
Restore the agent to a previous revision.
Arguments:
- revision_number: The revision number to restore.
434 async def delete_revision(self, revision_number: int) -> None: 435 """Delete a specific revision. 436 437 Args: 438 revision_number: The revision number to delete. 439 """ 440 await self._http.post( 441 "squid-api/v1/ai/agent/deleteRevision", 442 {"agentId": self._agent_id, "revisionNumber": revision_number}, 443 )
Delete a specific revision.
Arguments:
- revision_number: The revision number to delete.
395class AiAgent(TypedDict, total=False): 396 """A definition of an AI agent with its properties and default chat options. 397 398 Returned by :meth:`AiClient.list_agents`. 399 """ 400 401 id: str 402 """The unique identifier of the AI agent. Required.""" 403 createdAt: str 404 """ISO 8601 timestamp of when the agent was created. Required.""" 405 updatedAt: str 406 """ISO 8601 timestamp of when the agent was last updated. Required.""" 407 description: str 408 """An optional description of the agent's purpose or capabilities.""" 409 isPublic: bool 410 """Whether the agent is publicly accessible; defaults to False.""" 411 auditLog: bool 412 """Whether audit logging is enabled for the agent's activities; defaults to False.""" 413 auditLogFullContext: bool 414 """Whether the full agent context (system instructions and retrieved knowledge-base content) is recorded in the audit log; requires auditLog; defaults to False.""" 415 options: AiChatOptions 416 """The agent's default chat options, overridable by the user during use. Required.""" 417 apiKey: str 418 """Optional API key used specifically for operations on this agent.""" 419 mcpServer: AiAgentMcpServerConfig 420 """Optional configuration for exposing the agent as an MCP server."""
A definition of an AI agent with its properties and default chat options.
Returned by AiClient.list_agents().
Whether the full agent context (system instructions and retrieved knowledge-base content) is recorded in the audit log; requires auditLog; defaults to False.
The agent's default chat options, overridable by the user during use. Required.
142class AiAgentExecutionPlanOptions(TypedDict, total=False): 143 """Options for AI agent execution plan.""" 144 145 enabled: bool
Options for AI agent execution plan.
361class AiAgentMcpServerConfig(TypedDict, total=False): 362 """Configuration for exposing an AI agent as an MCP server at ``/mcp/<agentId>``.""" 363 364 enabled: bool 365 """Whether the agent is exposed as an MCP server. Required.""" 366 description: str 367 """Description of the MCP server, served as the ``instructions`` field of the MCP initialize result.""" 368 toolDescription: str 369 """Description of the MCP ``ask`` tool, exposed in the tools manifest.""" 370 oauthIntegrationId: str 371 """ID of an auth integration used to OAuth-protect the MCP server.""" 372 requireApiKey: bool 373 """Require the agent's API key as a bearer token; combinable with OAuth (either is accepted)."""
Configuration for exposing an AI agent as an MCP server at /mcp/<agentId>.
68class AiAgentMemoryOptions(TypedDict, total=False): 69 """Memory/session configuration for agent chat.""" 70 71 memoryId: str 72 """Unique memory ID. Reuse to continue a conversation.""" 73 memoryMode: AiMemoryMode 74 """How memory is used: 'read-write', 'read-only', 'write-only', 'disabled'."""
Memory/session configuration for agent chat.
182class AiAudioCreateSpeechOptions(TypedDict, total=False): 183 """Options for text-to-speech.""" 184 185 modelName: str 186 """'tts-1' or 'tts-1-hd'.""" 187 voice: str 188 """'alloy'|'ash'|'ballad'|'coral'|'echo'|'fable'|'onyx'|'nova'|'sage'|'shimmer'|'verse'.""" 189 responseFormat: str 190 """Audio output format.""" 191 instructions: str 192 """Extra instructions for speech generation.""" 193 speed: float 194 """Speech speed."""
Options for text-to-speech.
197class AiChatOptions(TypedDict, total=False): 198 """Full chat options for AI agent ask/chat operations. 199 200 Mirrors BaseAiChatOptions from the TypeScript SDK. 201 All fields are optional. 202 """ 203 204 model: AiChatModelSelection 205 """LLM model to use. String name or IntegrationModelSpec.""" 206 maxTokens: int 207 """Max input tokens for the AI model.""" 208 maxOutputTokens: int 209 """Max output tokens from the AI model.""" 210 temperature: float 211 """Sampling temperature (default 0.5).""" 212 instructions: str 213 """Extra instructions to include with the prompt.""" 214 functions: list[str] 215 """AI function IDs to expose to the agent.""" 216 memoryOptions: AiAgentMemoryOptions 217 """Memory/session configuration.""" 218 responseFormat: AiAgentResponseFormat 219 """Response format: 'text', 'json_object', or structured output.""" 220 includeReference: bool 221 """Include source references from context.""" 222 smoothTyping: bool 223 """Smooth typing effect for UI display (default true).""" 224 disableContext: bool 225 """Disable the whole context for this request.""" 226 enablePromptRewriteForRag: bool 227 """Rewrite prompt for RAG (default false).""" 228 agentContext: dict[str, Any] 229 """Global context passed to agent and all AI functions.""" 230 connectedAgents: list[AiConnectedAgentMetadata] 231 """Connected agents that can be called.""" 232 connectedIntegrations: list[AiConnectedIntegrationMetadata] 233 """Connected integrations.""" 234 connectedKnowledgeBases: list[AiConnectedKnowledgeBaseMetadata] 235 """Connected knowledge bases.""" 236 guardrails: GuardrailsOptions 237 """Guardrail options.""" 238 pii: AiPiiOptions 239 """PII screening. Read from the stored agent only; ignored when passed with a request.""" 240 contextMetadataFilterForKnowledgeBase: dict[str, Any] 241 """Metadata filters per knowledge base ID.""" 242 voiceOptions: AiAudioCreateSpeechOptions 243 """Options for voice response.""" 244 quotas: AiChatPromptQuotas 245 """Budget for nested AI calls.""" 246 executionPlanOptions: AiAgentExecutionPlanOptions 247 """Execution plan options.""" 248 fileUrls: list[AiFileUrl] 249 """File URLs to include in context.""" 250 fileIds: list[str] 251 """File IDs from AI provider's Files API.""" 252 reasoningEffort: AiReasoningEffort 253 """Reasoning effort level.""" 254 verbosity: AiVerbosityLevel 255 """Response verbosity level.""" 256 useCodeInterpreter: Literal["none", "llm"] 257 """Enable LLM's built-in code interpreter.""" 258 rerankProvider: AiRerankProvider 259 """Reranker provider for context (default 'cohere').""" 260 includeMetadata: bool 261 """Include metadata in context (deprecated).""" 262 timeoutMs: int 263 """Request timeout in milliseconds (default 240000)."""
Full chat options for AI agent ask/chat operations.
Mirrors BaseAiChatOptions from the TypeScript SDK. All fields are optional.
Response format: 'text', 'json_object', or structured output.
PII screening. Read from the stored agent only; ignored when passed with a request.
Metadata filters per knowledge base ID.
136class AiChatPromptQuotas(TypedDict, total=False): 137 """Budget for nested/recursive AI chat calls.""" 138 139 maxNestedCalls: int
Budget for nested/recursive AI chat calls.
37class AiClient: 38 """Entry point for AI operations: agents, knowledge base, audio, image. 39 40 Obtained via :meth:`Squid.ai()`. 41 42 Example:: 43 44 ai = squid.ai() 45 agent = ai.agent("my-agent") 46 kb = ai.knowledge_base("my-kb") 47 image_url = await ai.image().generate("a cat in space") 48 """ 49 50 def __init__(self, http: HttpTransport) -> None: 51 self._http = http 52 53 def agent(self, agent_id: str) -> AgentClient: 54 """Get a client for a specific AI agent. 55 56 Args: 57 agent_id: The unique agent identifier. 58 59 Returns: 60 An :class:`AgentClient` bound to the given agent ID. 61 """ 62 return AgentClient(self._http, agent_id) 63 64 def knowledge_base(self, knowledge_base_id: str) -> KnowledgeBaseClient: 65 """Get a client for a specific knowledge base. 66 67 Args: 68 knowledge_base_id: The unique knowledge base identifier. 69 70 Returns: 71 A :class:`KnowledgeBaseClient` bound to the given knowledge base ID. 72 """ 73 return KnowledgeBaseClient(self._http, knowledge_base_id) 74 75 def image(self) -> ImageClient: 76 """Get a client for image generation and processing. 77 78 Returns: 79 An :class:`ImageClient` instance. 80 """ 81 return ImageClient(self._http) 82 83 def audio(self) -> AudioClient: 84 """Get a client for audio transcription and speech synthesis. 85 86 Returns: 87 An :class:`AudioClient` instance. 88 """ 89 return AudioClient(self._http) 90 91 async def list_agents(self) -> list[AiAgent]: 92 """List all AI agents defined for the application. 93 94 Returns: 95 A list of ``AiAgent`` dicts. Empty list if no agents are defined. 96 """ 97 result = await self._http.get("squid-api/v1/ai/agent/listAgents") 98 return result.get("agents", []) if result else [] 99 100 async def list_knowledge_bases(self) -> list[AiKnowledgeBase]: 101 """List all AI knowledge bases defined for the application. 102 103 Returns: 104 A list of ``AiKnowledgeBase`` dicts. Empty list if no knowledge 105 bases are defined. 106 """ 107 result = await self._http.get("squid-api/v1/ai/knowledge-base/listKnowledgeBases") 108 return result.get("knowledgeBases", []) if result else [] 109 110 async def list_chat_models(self, include_deprecated: bool = False) -> list[ModelIdSpec]: 111 """List all AI chat models available to the application. 112 113 Includes both Squid-provided vendor models and any custom integration 114 models configured for the app. 115 116 Args: 117 include_deprecated: When True, deprecated vendor models are 118 included and marked with ``replacedBy``. Defaults to False. 119 120 Returns: 121 A list of ``ModelIdSpec`` dicts, each with ``modelId``, an optional 122 ``integrationId``, and a human-readable ``displayName``. Vendor 123 models also carry a ``description``, and deprecated vendor models a 124 ``replacedBy`` with the active model their calls are routed to. 125 """ 126 params = {"includeDeprecated": "true"} if include_deprecated else None 127 result = await self._http.get("squid-api/v1/ai/settings/listChatModels", params=params) 128 return result.get("models", []) if result else [] 129 130 async def list_functions(self) -> list[AiFunctionMetadata]: 131 """List all AI functions registered for the application's deployed bundle. 132 133 Returns: 134 A list of ``AiFunctionMetadata`` dicts. Empty list if no functions 135 are registered. 136 """ 137 result = await self._http.get("squid-api/v1/ai/function/listFunctions") 138 return result.get("functions", []) if result else []
Entry point for AI operations: agents, knowledge base, audio, image.
Obtained via Squid.ai()().
Example::
ai = squid.ai()
agent = ai.agent("my-agent")
kb = ai.knowledge_base("my-kb")
image_url = await ai.image().generate("a cat in space")
53 def agent(self, agent_id: str) -> AgentClient: 54 """Get a client for a specific AI agent. 55 56 Args: 57 agent_id: The unique agent identifier. 58 59 Returns: 60 An :class:`AgentClient` bound to the given agent ID. 61 """ 62 return AgentClient(self._http, agent_id)
Get a client for a specific AI agent.
Arguments:
- agent_id: The unique agent identifier.
Returns:
An
AgentClientbound to the given agent ID.
64 def knowledge_base(self, knowledge_base_id: str) -> KnowledgeBaseClient: 65 """Get a client for a specific knowledge base. 66 67 Args: 68 knowledge_base_id: The unique knowledge base identifier. 69 70 Returns: 71 A :class:`KnowledgeBaseClient` bound to the given knowledge base ID. 72 """ 73 return KnowledgeBaseClient(self._http, knowledge_base_id)
Get a client for a specific knowledge base.
Arguments:
- knowledge_base_id: The unique knowledge base identifier.
Returns:
A
KnowledgeBaseClientbound to the given knowledge base ID.
91 async def list_agents(self) -> list[AiAgent]: 92 """List all AI agents defined for the application. 93 94 Returns: 95 A list of ``AiAgent`` dicts. Empty list if no agents are defined. 96 """ 97 result = await self._http.get("squid-api/v1/ai/agent/listAgents") 98 return result.get("agents", []) if result else []
List all AI agents defined for the application.
Returns:
A list of
AiAgentdicts. Empty list if no agents are defined.
100 async def list_knowledge_bases(self) -> list[AiKnowledgeBase]: 101 """List all AI knowledge bases defined for the application. 102 103 Returns: 104 A list of ``AiKnowledgeBase`` dicts. Empty list if no knowledge 105 bases are defined. 106 """ 107 result = await self._http.get("squid-api/v1/ai/knowledge-base/listKnowledgeBases") 108 return result.get("knowledgeBases", []) if result else []
List all AI knowledge bases defined for the application.
Returns:
A list of
AiKnowledgeBasedicts. Empty list if no knowledge bases are defined.
110 async def list_chat_models(self, include_deprecated: bool = False) -> list[ModelIdSpec]: 111 """List all AI chat models available to the application. 112 113 Includes both Squid-provided vendor models and any custom integration 114 models configured for the app. 115 116 Args: 117 include_deprecated: When True, deprecated vendor models are 118 included and marked with ``replacedBy``. Defaults to False. 119 120 Returns: 121 A list of ``ModelIdSpec`` dicts, each with ``modelId``, an optional 122 ``integrationId``, and a human-readable ``displayName``. Vendor 123 models also carry a ``description``, and deprecated vendor models a 124 ``replacedBy`` with the active model their calls are routed to. 125 """ 126 params = {"includeDeprecated": "true"} if include_deprecated else None 127 result = await self._http.get("squid-api/v1/ai/settings/listChatModels", params=params) 128 return result.get("models", []) if result else []
List all AI chat models available to the application.
Includes both Squid-provided vendor models and any custom integration models configured for the app.
Arguments:
- include_deprecated: When True, deprecated vendor models are
included and marked with
replacedBy. Defaults to False.
Returns:
A list of
ModelIdSpecdicts, each withmodelId, an optionalintegrationId, and a human-readabledisplayName. Vendor models also carry adescription, and deprecated vendor models areplacedBywith the active model their calls are routed to.
130 async def list_functions(self) -> list[AiFunctionMetadata]: 131 """List all AI functions registered for the application's deployed bundle. 132 133 Returns: 134 A list of ``AiFunctionMetadata`` dicts. Empty list if no functions 135 are registered. 136 """ 137 result = await self._http.get("squid-api/v1/ai/function/listFunctions") 138 return result.get("functions", []) if result else []
List all AI functions registered for the application's deployed bundle.
Returns:
A list of
AiFunctionMetadatadicts. Empty list if no functions are registered.
77class AiConnectedAgentMetadata(TypedDict): 78 """Metadata for a connected agent.""" 79 80 agentId: str 81 description: str
Metadata for a connected agent.
84class AiConnectedIntegrationMetadata(TypedDict, total=False): 85 """Metadata for a connected integration. 86 87 ``integrationId`` and ``integrationType`` are required by the platform API; 88 the remaining fields are optional. 89 """ 90 91 integrationId: str 92 """The ID of the connected integration. Required.""" 93 integrationType: str 94 """The integration type, e.g. 'hubspot', 'slack', 'api'. Required.""" 95 description: str 96 """Optional description used as the AI function description for the parent agent.""" 97 instructions: str 98 """Optional instructions for the connected integration agent, overriding the default.""" 99 functionsToUse: list[str] 100 """AI function IDs the agent may use. Omit for all functions; [] for none.""" 101 options: dict[str, Any] 102 """Additional integration options interpreted by Squid Core or connector AI functions.""" 103 connectedAsMcp: bool 104 """Treat this integration as an MCP server (API integrations with exposeAsMcpServer)."""
Metadata for a connected integration.
integrationId and integrationType are required by the platform API;
the remaining fields are optional.
Optional instructions for the connected integration agent, overriding the default.
107class AiConnectedKnowledgeBaseMetadata(TypedDict, total=False): 108 """Metadata for a connected knowledge base.""" 109 110 knowledgeBaseId: str 111 description: str 112 includeMetadata: bool
Metadata for a connected knowledge base.
574class AiContextFileOptions(TypedDict, total=False): 575 """Options for file context processing.""" 576 577 chunkOverlap: int 578 ragType: str
Options for file context processing.
554class AiContextTextOptions(TypedDict, total=False): 555 """Options for text context processing.""" 556 557 chunkOverlap: int 558 """Amount of chunk overlap in characters.""" 559 ragType: str 560 """The type of RAG to use."""
Options for text context processing.
115class AiFileUrl(TypedDict, total=False): 116 """File URL to include in chat context.""" 117 118 id: str 119 type: str 120 purpose: str 121 url: str 122 description: str 123 fileName: str
File URL to include in chat context.
692class AiFunctionAttributes(TypedDict, total=False): 693 """Additional optional readonly metadata for an AI function.""" 694 695 integrationType: list[str] 696 """Types of integration this function is used for. Functions with a defined 697 'integrationType' require 'integrationId' to be passed as part of the function context."""
Additional optional readonly metadata for an AI function.
700class AiFunctionMetadata(TypedDict, total=False): 701 """Metadata describing an AI function available in the application. 702 703 Returned by :meth:`AiClient.list_functions`. 704 """ 705 706 serviceFunction: str 707 """The fully qualified name of the function ('ServiceName:functionName'). Required.""" 708 description: str 709 """Description of what the function does.""" 710 promptId: str 711 """Opaque ID of a registered prompt that supplies this function's description; 712 resolved server-side.""" 713 params: list[AiFunctionParam] 714 """Parameters that the function accepts. Required.""" 715 attributes: AiFunctionAttributes 716 """Additional attributes for the function.""" 717 categories: list[str] 718 """Categories this function belongs to.""" 719 internal: bool 720 """Whether this function is internal and not meant for direct use."""
Metadata describing an AI function available in the application.
Returned by AiClient.list_functions().
The fully qualified name of the function ('ServiceName:functionName'). Required.
677class AiFunctionParam(TypedDict, total=False): 678 """Defines the structure of a parameter for an AI function.""" 679 680 name: str 681 """Name of the parameter. Required.""" 682 description: str 683 """Description of the parameter's purpose. Required.""" 684 type: AiFunctionParamType 685 """Data type of the parameter. Required.""" 686 required: bool 687 """Indicates if the parameter is mandatory. Required.""" 688 enum: list[str] 689 """List of possible values for the parameter, if applicable."""
Defines the structure of a parameter for an AI function.
525class AiKnowledgeBase(TypedDict, total=False): 526 """An AI knowledge base that can be attached to an AI agent. 527 528 Returned by :meth:`AiClient.list_knowledge_bases`. 529 """ 530 531 id: str 532 """The unique identifier of the knowledge base. Required.""" 533 appId: str 534 """The app ID that the knowledge base belongs to. Required.""" 535 description: str 536 """The user's description of the knowledge base. Required.""" 537 metadataFields: list[AiKnowledgeBaseMetadataField] 538 """Predefined metadata fields that can be used for filtering. Required.""" 539 embeddingModel: AiEmbeddingsModelSelection 540 """The embedding model used by this knowledge base. Required.""" 541 chatModel: AiChatModelSelection 542 """The model used when asking questions of this knowledge base. Required.""" 543 vectorDbType: VectorDbType 544 """The vector store backend the knowledge base reads/writes from. Set at creation 545 and immutable thereafter. Absent on older records.""" 546 graphRag: AiKnowledgeBaseGraphConfig 547 """Opt-in GraphRAG configuration. Only honored for ``vectorDbType: 'mongoAtlas'`` 548 knowledge bases; enables per-chunk entity/relationship extraction at ingest and 549 ``searchMode: 'graph'`` at query time.""" 550 updatedAt: str 551 """ISO 8601 timestamp of when the knowledge base was last updated. Required."""
An AI knowledge base that can be attached to an AI agent.
Returned by AiClient.list_knowledge_bases().
Predefined metadata fields that can be used for filtering. Required.
The embedding model used by this knowledge base. Required.
The model used when asking questions of this knowledge base. Required.
The vector store backend the knowledge base reads/writes from. Set at creation and immutable thereafter. Absent on older records.
Opt-in GraphRAG configuration. Only honored for vectorDbType: 'mongoAtlas'
knowledge bases; enables per-chunk entity/relationship extraction at ingest and
searchMode: 'graph' at query time.
478class AiKnowledgeBaseGraphConceptsConfig(TypedDict, total=False): 479 """Configuration of the graph's concept layer (facet taxonomies).""" 480 481 facets: Union[list[str], Literal["auto"]] 482 """Which metadata fields become value facets. ``'auto'`` (the default) profiles the KB's 483 context metadata and selects the categorical fields; an explicit list overrides 484 auto-selection; an empty list disables value facets.""" 485 pathFacets: list[AiKnowledgeBaseGraphPathFacetConfig] 486 """Explicit path facets, e.g. ``[{'field': 'folderPath', 'type': 'path'}]``. A path facet 487 always builds when its field has values, independent of ``facets``."""
Configuration of the graph's concept layer (facet taxonomies).
Which metadata fields become value facets. 'auto' (the default) profiles the KB's
context metadata and selects the categorical fields; an explicit list overrides
auto-selection; an empty list disables value facets.
Explicit path facets, e.g. [{'field': 'folderPath', 'type': 'path'}]. A path facet
always builds when its field has values, independent of facets.
502class AiKnowledgeBaseGraphConfig(_AiKnowledgeBaseGraphConfigRequired, total=False): 503 """Per-knowledge-base GraphRAG configuration. 504 505 Opt-in and mutable (unlike ``embeddingModel``/``vectorDbType``); only honored for 506 ``vectorDbType: 'mongoAtlas'`` knowledge bases. Enabling it on a knowledge base that 507 already has content backfills the graph automatically once the KB goes quiet. 508 509 On upsert the supplied value replaces the stored config rather than merging into it, 510 so include every key that should remain set. 511 """ 512 513 extractionModel: AiChatModelSelection 514 """Chat model used for per-chunk entity/relationship extraction. Defaults to the server's 515 graph model.""" 516 entityTypes: list[str] 517 """Optional domain taxonomy hint (entity types) injected into the extraction prompt.""" 518 autoBuildDebounceMs: int 519 """Quiet window (milliseconds) after the last graph activity before the sweep auto-builds 520 the structure. Must be a positive integer. Defaults to the server's window (5 minutes).""" 521 concepts: AiKnowledgeBaseGraphConceptsConfig 522 """Concept-layer (facet taxonomy) configuration. Omitted means ``facets: 'auto'``."""
Per-knowledge-base GraphRAG configuration.
Opt-in and mutable (unlike embeddingModel/vectorDbType); only honored for
vectorDbType: 'mongoAtlas' knowledge bases. Enabling it on a knowledge base that
already has content backfills the graph automatically once the KB goes quiet.
On upsert the supplied value replaces the stored config rather than merging into it, so include every key that should remain set.
Chat model used for per-chunk entity/relationship extraction. Defaults to the server's graph model.
Optional domain taxonomy hint (entity types) injected into the extraction prompt.
Quiet window (milliseconds) after the last graph activity before the sweep auto-builds the structure. Must be a positive integer. Defaults to the server's window (5 minutes).
Concept-layer (facet taxonomy) configuration. Omitted means facets: 'auto'.
618class AiKnowledgeBaseGraphFilter(TypedDict): 619 """Graph scope for a knowledge-base search: restricts results to the documents under one 620 concept of the KB's graph. Composes with every ``searchMode``. Requires ``graphRag.enabled``.""" 621 622 underConcept: str 623 """The concept to scope to: a facet nodeId (``facet_…`` — exact) or a concept name, 624 resolved server-side (exact, then alias, then similarity). An unresolvable ref fails with 625 ``CONCEPT_NOT_FOUND`` and the nearest matching concept names."""
Graph scope for a knowledge-base search: restricts results to the documents under one
concept of the KB's graph. Composes with every searchMode. Requires graphRag.enabled.
469class AiKnowledgeBaseGraphPathFacetConfig( 470 _AiKnowledgeBaseGraphPathFacetConfigRequired, total=False 471): 472 """A path facet: a deterministic tree built by splitting a hierarchical path field.""" 473 474 separator: str 475 """Path segment separator. Defaults to ``'/'``."""
A path facet: a deterministic tree built by splitting a hierarchical path field.
604class AiKnowledgeBaseGraphSearchOptions(TypedDict, total=False): 605 """Tuning for ``searchMode: 'graph'`` (GraphRAG) retrieval. Ignored for other search modes.""" 606 607 seedLimit: int 608 """Entities seeded via vector search before graph expansion. Default 8, max 25.""" 609 maxHops: int 610 """Number of hops to expand from each seed (traversal depth + 1). Default 2, max 3.""" 611 includeGraphContext: bool 612 """When True, the server attaches the traversed subgraph to the search response as 613 ``graphContext``. Default False. Read it via 614 :meth:`~squidcloud.ai.KnowledgeBaseClient.search_with_graph_context`; 615 :meth:`~squidcloud.ai.KnowledgeBaseClient.search` returns only the chunks."""
Tuning for searchMode: 'graph' (GraphRAG) retrieval. Ignored for other search modes.
When True, the server attaches the traversed subgraph to the search response as
graphContext. Default False. Read it via
~squidcloud.ai.KnowledgeBaseClient.search_with_graph_context();
~squidcloud.ai.KnowledgeBaseClient.search() returns only the chunks.
426class AiKnowledgeBaseMetadataField(TypedDict, total=False): 427 """Metadata field definition for a knowledge base.""" 428 429 name: str 430 dataType: str 431 required: bool 432 description: str
Metadata field definition for a knowledge base.
163class AiPiiOptions(TypedDict, total=False): 164 """Refuses prompts carrying PII before they reach the agent's model. 165 166 The inverse of GuardrailsOptions.disablePii, which asks the agent's own model 167 not to emit PII in its answer. 168 """ 169 170 onDetect: str 171 """'reject' refuses a prompt carrying PII; 'off' (default) disables screening.""" 172 entities: list[str] 173 """Entity kinds to screen for: 'email', 'phoneNumber', 'creditCard', 'ssn', 'iban', 'passport'.""" 174 customRules: list[str] 175 """App-specific PII described in plain language, screened by classifierModel.""" 176 classifierModel: AiChatModelSelection 177 """Model screening customRules. Defaults to 'gpt-5.6-luna'.""" 178 allowList: list[str] 179 """Literal values that never count as PII."""
Refuses prompts carrying PII before they reach the agent's model.
The inverse of GuardrailsOptions.disablePii, which asks the agent's own model not to emit PII in its answer.
Entity kinds to screen for: 'email', 'phoneNumber', 'creditCard', 'ssn', 'iban', 'passport'.
Model screening customRules. Defaults to 'gpt-5.6-luna'.
310class AiQueryAnalyzeResultsOptions(TypedDict, total=False): 311 """Options for the result-analysis stage of AI query.""" 312 313 disabled: bool 314 """When true, skip analysis and return raw results only.""" 315 enableCodeInterpreter: bool 316 """Enable code interpreter mode (default false).""" 317 aiOptions: AiChatOptions 318 """Customize AI agent behavior used by the stage.""" 319 agentId: AiAgentId 320 """If set, use this agent to analyze results and produce the final answer."""
Options for the result-analysis stage of AI query.
296class AiQueryGenerateQueryOptions(TypedDict, total=False): 297 """Options for the query-generation stage of AI query.""" 298 299 aiOptions: AiChatOptions 300 """Customize AI agent behavior used by the stage.""" 301 maxErrorCorrections: int 302 """Number of retries due to errors in a generated AI query (default 2).""" 303 agentId: AiAgentId 304 """If set, use this agent to generate the query.""" 305 allowClarification: bool 306 """When true, allow the AI to ask a clarifying question instead of 307 generating a query for ambiguous prompts (default false)."""
Options for the query-generation stage of AI query.
332class AiQueryOptions(TypedDict, total=False): 333 """Options for configuring AI query execution. 334 335 Mirrors ``AiQueryOptions`` from the TypeScript SDK. All fields optional. 336 """ 337 338 instructions: str 339 """Custom instructions applied to all stages unless overridden per-stage.""" 340 enableRawResults: bool 341 """Enable raw results output.""" 342 selectCollectionsOptions: AiQuerySelectCollectionsOptions 343 """Collection-selection stage options.""" 344 generateQueryOptions: AiQueryGenerateQueryOptions 345 """Query-generation stage options.""" 346 analyzeResultsOptions: AiQueryAnalyzeResultsOptions 347 """Result-analysis stage options.""" 348 sessionContext: AiSessionContext 349 """Session information (``agentId`` may be omitted).""" 350 memoryOptions: AiAgentMemoryOptions 351 """Memory/session configuration.""" 352 generateQueriesOnly: bool 353 """If true, return generated queries without executing or analyzing them.""" 354 validateWithAiOptions: AiQueryValidateWithAiOptions 355 """Optional AI validation of generated queries."""
Options for configuring AI query execution.
Mirrors AiQueryOptions from the TypeScript SDK. All fields optional.
285class AiQuerySelectCollectionsOptions(TypedDict, total=False): 286 """Options for the collection-selection stage of AI query.""" 287 288 collectionsToUse: list[str] 289 """Restrict query to these collections. Defaults to all collections.""" 290 runMode: AiQueryCollectionsSelectionRunMode 291 """Stage behavior: 'default', 'force', or 'disable'.""" 292 aiOptions: AiChatOptions 293 """Customize AI agent behavior used by the stage."""
Options for the collection-selection stage of AI query.
323class AiQueryValidateWithAiOptions(TypedDict, total=False): 324 """Options for AI-based validation of generated queries.""" 325 326 enabled: bool 327 """Whether AI validation is enabled.""" 328 aiOptions: AiChatOptions 329 """Defaults to the same model used for query generation."""
Options for AI-based validation of generated queries.
272class AiSessionContext(TypedDict, total=False): 273 """Session context for AI query execution. 274 275 Mirrors the TypeScript ``AiSessionContext`` type. All fields optional 276 here because the query endpoint accepts a partial context (``agentId`` 277 may be omitted). 278 """ 279 280 clientId: str 281 agentId: str 282 jobId: str
Session context for AI query execution.
Mirrors the TypeScript AiSessionContext type. All fields optional
here because the query endpoint accepts a partial context (agentId
may be omitted).
126class AiStructuredOutputFormat(TypedDict): 127 """Structured output format for JSON responses.""" 128 129 type: Literal["json_schema"] 130 schema: dict[str, Any]
Structured output format for JSON responses.
915class AudioClient: 916 """Audio transcription and speech synthesis. 917 918 Obtained via :meth:`AiClient.audio`. 919 920 Example:: 921 922 text = await squid.ai().audio().transcribe(audio_bytes) 923 speech = await squid.ai().audio().create_speech("Hello!", options={"voice": "nova"}) 924 """ 925 926 def __init__(self, http: HttpTransport) -> None: 927 self._http = http 928 929 async def transcribe( 930 self, 931 audio_data: bytes, 932 filename: str = "audio.wav", 933 content_type: str = "audio/wav", 934 *, 935 options: dict[str, Any] | None = None, 936 ) -> str: 937 """Transcribe audio to text. 938 939 Args: 940 audio_data: The audio file content as bytes. 941 filename: The filename (used in the multipart upload). 942 content_type: The MIME type of the audio file. 943 options: Provider-specific transcription options. 944 945 Returns: 946 The transcribed text. 947 """ 948 form_data: dict[str, str] = { 949 "optionsJson": json.dumps(options or {}), 950 } 951 result = await self._http.post_form( 952 "squid-api/v1/ai/audio/transcribe", 953 data=form_data, 954 files=[("file", (filename, audio_data, content_type))], 955 ) 956 return result if isinstance(result, str) else str(result) 957 958 async def create_speech( 959 self, 960 text: str, 961 options: AiAudioCreateSpeechOptions, 962 ) -> bytes: 963 """Generate speech audio from text. 964 965 Args: 966 text: The text to convert to speech. 967 options: Speech generation options. See :class:`AiAudioCreateSpeechOptions`. 968 Required keys: ``modelName`` (e.g., ``'tts-1'``), ``voice`` 969 (e.g., ``'nova'``, ``'alloy'``). 970 971 Returns: 972 Raw audio file bytes (e.g., MP3 format by default). 973 974 Example:: 975 976 audio_data = ( 977 await squid.ai() 978 .audio() 979 .create_speech( 980 "Hello!", 981 options={ 982 "modelName": "tts-1", 983 "voice": "nova", 984 }, 985 ) 986 ) 987 with open("speech.mp3", "wb") as f: 988 f.write(audio_data) 989 """ 990 return await self._http.post( 991 "squid-api/v1/ai/audio/createSpeech", 992 {"input": text, "options": options}, 993 )
Audio transcription and speech synthesis.
Obtained via AiClient.audio().
Example::
text = await squid.ai().audio().transcribe(audio_bytes)
speech = await squid.ai().audio().create_speech("Hello!", options={"voice": "nova"})
929 async def transcribe( 930 self, 931 audio_data: bytes, 932 filename: str = "audio.wav", 933 content_type: str = "audio/wav", 934 *, 935 options: dict[str, Any] | None = None, 936 ) -> str: 937 """Transcribe audio to text. 938 939 Args: 940 audio_data: The audio file content as bytes. 941 filename: The filename (used in the multipart upload). 942 content_type: The MIME type of the audio file. 943 options: Provider-specific transcription options. 944 945 Returns: 946 The transcribed text. 947 """ 948 form_data: dict[str, str] = { 949 "optionsJson": json.dumps(options or {}), 950 } 951 result = await self._http.post_form( 952 "squid-api/v1/ai/audio/transcribe", 953 data=form_data, 954 files=[("file", (filename, audio_data, content_type))], 955 ) 956 return result if isinstance(result, str) else str(result)
Transcribe audio to text.
Arguments:
- audio_data: The audio file content as bytes.
- filename: The filename (used in the multipart upload).
- content_type: The MIME type of the audio file.
- options: Provider-specific transcription options.
Returns:
The transcribed text.
958 async def create_speech( 959 self, 960 text: str, 961 options: AiAudioCreateSpeechOptions, 962 ) -> bytes: 963 """Generate speech audio from text. 964 965 Args: 966 text: The text to convert to speech. 967 options: Speech generation options. See :class:`AiAudioCreateSpeechOptions`. 968 Required keys: ``modelName`` (e.g., ``'tts-1'``), ``voice`` 969 (e.g., ``'nova'``, ``'alloy'``). 970 971 Returns: 972 Raw audio file bytes (e.g., MP3 format by default). 973 974 Example:: 975 976 audio_data = ( 977 await squid.ai() 978 .audio() 979 .create_speech( 980 "Hello!", 981 options={ 982 "modelName": "tts-1", 983 "voice": "nova", 984 }, 985 ) 986 ) 987 with open("speech.mp3", "wb") as f: 988 f.write(audio_data) 989 """ 990 return await self._http.post( 991 "squid-api/v1/ai/audio/createSpeech", 992 {"input": text, "options": options}, 993 )
Generate speech audio from text.
Arguments:
- text: The text to convert to speech.
- options: Speech generation options. See
AiAudioCreateSpeechOptions. Required keys:modelName(e.g.,'tts-1'),voice(e.g.,'nova','alloy').
Returns:
Raw audio file bytes (e.g., MP3 format by default).
Example::
audio_data = (
await squid.ai()
.audio()
.create_speech(
"Hello!",
options={
"modelName": "tts-1",
"voice": "nova",
},
)
)
with open("speech.mp3", "wb") as f:
f.write(audio_data)
829class CreatePdfDimensionsOptions(TypedDict): 830 """PDF output options by custom dimensions.""" 831 832 type: Literal["dimensions"] 833 width: int 834 """Width in pixels.""" 835 height: int 836 """Height in pixels."""
PDF output options by custom dimensions.
810class CreatePdfFormatOptions(TypedDict): 811 """PDF output options by format.""" 812 813 type: Literal["format"] 814 format: Literal[ 815 "letter", 816 "legal", 817 "tabloid", 818 "ledger", 819 "a0", 820 "a1", 821 "a2", 822 "a3", 823 "a4", 824 "a5", 825 "a6", 826 ]
PDF output options by format.
842class ExtractDataFromDocumentOptions(TypedDict, total=False): 843 """Options for document data extraction.""" 844 845 extractImages: bool 846 """Whether to extract embedded images. Defaults to True.""" 847 imageMinSizePixels: int 848 """Minimum image size to extract.""" 849 pageIndexes: list[int] 850 """Specific pages to extract (0-based).""" 851 preferredExtractionMethod: str 852 discardOriginalFile: bool
Options for document data extraction.
17class ExtractionClient: 18 """Document extraction and PDF creation.""" 19 20 def __init__(self, http: HttpTransport) -> None: 21 self._http = http 22 23 async def create_pdf_from_html( 24 self, 25 inner_html: str, 26 *, 27 title: str | None = None, 28 css_url: str | None = None, 29 output_options: CreatePdfOutputOptions | None = None, 30 ) -> dict: 31 """Create a PDF from HTML content. 32 33 Returns CreatePdfResponse with 'url' and 'fileName'. 34 """ 35 body: dict[str, Any] = {"type": "html", "innerHtml": inner_html} 36 if title is not None: 37 body["title"] = title 38 if css_url is not None: 39 body["cssUrl"] = css_url 40 if output_options is not None: 41 body["outputOptions"] = output_options 42 return await self._http.post("squid-api/v1/extraction/createPdf", body) 43 44 async def create_pdf_from_url( 45 self, 46 url: str, 47 *, 48 title: str | None = None, 49 output_options: CreatePdfOutputOptions | None = None, 50 ) -> dict: 51 """Create a PDF from a URL. 52 53 Returns CreatePdfResponse with 'url' and 'fileName'. 54 """ 55 body: dict[str, Any] = {"type": "url", "url": url} 56 if title is not None: 57 body["title"] = title 58 if output_options is not None: 59 body["outputOptions"] = output_options 60 return await self._http.post("squid-api/v1/extraction/createPdf", body) 61 62 async def extract_data_from_document_url( 63 self, 64 url: str, 65 options: ExtractDataFromDocumentOptions | None = None, 66 ) -> dict: 67 """Extract structured data from a document URL. 68 69 Returns ExtractDataFromDocumentResponse with 'pages' and optional 'longTermStoragePath'. 70 """ 71 body: dict[str, Any] = {"url": url} 72 if options is not None: 73 body["options"] = options 74 return await self._http.post("squid-api/v1/extraction/extractDataFromDocumentUrl", body) 75 76 async def extract_data_from_document_file( 77 self, 78 file_data: bytes, 79 filename: str, 80 content_type: str = "application/pdf", 81 options: ExtractDataFromDocumentOptions | None = None, 82 ) -> dict: 83 """Extract structured data from a document file. 84 85 Returns ExtractDataFromDocumentResponse with 'pages' and optional 'longTermStoragePath'. 86 """ 87 request: dict[str, Any] = {} 88 if options is not None: 89 request["options"] = options 90 form_data = {"request": json.dumps(request)} 91 92 return await self._http.post_form( 93 "squid-api/v1/extraction/extractDataFromDocumentFile", 94 data=form_data, 95 files=[("file", (filename, file_data, content_type))], 96 )
Document extraction and PDF creation.
23 async def create_pdf_from_html( 24 self, 25 inner_html: str, 26 *, 27 title: str | None = None, 28 css_url: str | None = None, 29 output_options: CreatePdfOutputOptions | None = None, 30 ) -> dict: 31 """Create a PDF from HTML content. 32 33 Returns CreatePdfResponse with 'url' and 'fileName'. 34 """ 35 body: dict[str, Any] = {"type": "html", "innerHtml": inner_html} 36 if title is not None: 37 body["title"] = title 38 if css_url is not None: 39 body["cssUrl"] = css_url 40 if output_options is not None: 41 body["outputOptions"] = output_options 42 return await self._http.post("squid-api/v1/extraction/createPdf", body)
Create a PDF from HTML content.
Returns CreatePdfResponse with 'url' and 'fileName'.
44 async def create_pdf_from_url( 45 self, 46 url: str, 47 *, 48 title: str | None = None, 49 output_options: CreatePdfOutputOptions | None = None, 50 ) -> dict: 51 """Create a PDF from a URL. 52 53 Returns CreatePdfResponse with 'url' and 'fileName'. 54 """ 55 body: dict[str, Any] = {"type": "url", "url": url} 56 if title is not None: 57 body["title"] = title 58 if output_options is not None: 59 body["outputOptions"] = output_options 60 return await self._http.post("squid-api/v1/extraction/createPdf", body)
Create a PDF from a URL.
Returns CreatePdfResponse with 'url' and 'fileName'.
62 async def extract_data_from_document_url( 63 self, 64 url: str, 65 options: ExtractDataFromDocumentOptions | None = None, 66 ) -> dict: 67 """Extract structured data from a document URL. 68 69 Returns ExtractDataFromDocumentResponse with 'pages' and optional 'longTermStoragePath'. 70 """ 71 body: dict[str, Any] = {"url": url} 72 if options is not None: 73 body["options"] = options 74 return await self._http.post("squid-api/v1/extraction/extractDataFromDocumentUrl", body)
Extract structured data from a document URL.
Returns ExtractDataFromDocumentResponse with 'pages' and optional 'longTermStoragePath'.
76 async def extract_data_from_document_file( 77 self, 78 file_data: bytes, 79 filename: str, 80 content_type: str = "application/pdf", 81 options: ExtractDataFromDocumentOptions | None = None, 82 ) -> dict: 83 """Extract structured data from a document file. 84 85 Returns ExtractDataFromDocumentResponse with 'pages' and optional 'longTermStoragePath'. 86 """ 87 request: dict[str, Any] = {} 88 if options is not None: 89 request["options"] = options 90 form_data = {"request": json.dumps(request)} 91 92 return await self._http.post_form( 93 "squid-api/v1/extraction/extractDataFromDocumentFile", 94 data=form_data, 95 files=[("file", (filename, file_data, content_type))], 96 )
Extract structured data from a document file.
Returns ExtractDataFromDocumentResponse with 'pages' and optional 'longTermStoragePath'.
581class FileContextRequest(TypedDict, total=False): 582 """Request to upsert a file context.""" 583 584 contextId: str 585 type: Literal["file"] 586 metadata: dict[str, Any] 587 extractImages: bool 588 """Whether to extract and describe images in the file. Defaults to True. 589 590 This is the opposite of the text context default, which is False: a file's charts and 591 scanned pages carry content its text layer does not, while images referenced from pasted 592 markdown/HTML are usually layout chrome. 593 """ 594 imageMinSizePixels: int 595 extractionModel: AiChatModelSelection 596 options: AiContextFileOptions 597 preferredExtractionMethod: str 598 discardOriginalFile: bool
Request to upsert a file context.
Whether to extract and describe images in the file. Defaults to True.
This is the opposite of the text context default, which is False: a file's charts and scanned pages carry content its text layer does not, while images referenced from pasted markdown/HTML are usually layout chrome.
742class FluxOptions(TypedDict, total=False): 743 """Options for Flux image generation.""" 744 745 modelName: Literal["flux-pro-1.1", "flux-kontext-pro"] 746 width: int 747 """Must be multiple of 32, min 256, max 1440.""" 748 height: int 749 """Must be multiple of 32, min 256, max 1440.""" 750 prompt_upsampling: bool 751 seed: int 752 safety_tolerance: int 753 """1 (strict) to 5 (permissive)."""
Options for Flux image generation.
726class GptImageOptions(TypedDict, total=False): 727 """Options for OpenAI gpt-image-* family image generation.""" 728 729 modelName: Literal[ 730 "gpt-image-1", 731 "gpt-image-1-mini", 732 "gpt-image-1.5", 733 "gpt-image-2", 734 "gpt-image-2-2026-04-21", 735 "chatgpt-image-latest", 736 ] 737 quality: Literal["auto", "high", "medium", "low"] 738 size: Literal["1024x1024", "1024x1536", "1536x1024", "auto"] 739 numberOfImagesToGenerate: int
Options for OpenAI gpt-image-* family image generation.
148class GuardrailsOptions(TypedDict, total=False): 149 """Guardrail options for agent responses.""" 150 151 custom: str 152 """A custom guardrail instruction.""" 153 disablePii: bool 154 """Disables personally identifiable information if true.""" 155 professionalTone: bool 156 """Enforces a professional tone if true.""" 157 offTopicAnswers: bool 158 """Prevents off-topic answers if true.""" 159 disableProfanity: bool 160 """Disables profanity if true."""
Guardrail options for agent responses.
841class ImageClient: 842 """Image generation and processing. 843 844 Supports DALL-E, Stable Diffusion Core, and Flux models. 845 846 Obtained via :meth:`AiClient.image`. 847 848 Example:: 849 850 image_url = ( 851 await squid.ai() 852 .image() 853 .generate( 854 "a cat astronaut on the moon", 855 options={"modelName": "gpt-image-1", "quality": "high"}, 856 ) 857 ) 858 """ 859 860 def __init__(self, http: HttpTransport) -> None: 861 self._http = http 862 863 async def generate( 864 self, 865 prompt: str, 866 options: ImageGenerateOptions | None = None, 867 ) -> str: 868 """Generate an image from a text prompt. 869 870 Args: 871 prompt: A text description of the image to generate. 872 options: Provider-specific generation options. Use one of: 873 - :class:`GptImageOptions`: ``{'modelName': 'gpt-image-1', 'quality': 'high', 'size': '1024x1024'}`` 874 - :class:`FluxOptions`: ``{'modelName': 'flux-pro-1.1', 'width': 1024, 'height': 768}`` 875 - :class:`StableDiffusionOptions`: ``{'modelName': 'stable-diffusion-core', 'aspectRatio': '16:9'}`` 876 877 Returns: 878 The URL of the generated image. 879 """ 880 result = await self._http.post( 881 "squid-api/v1/ai/image/generate", 882 {"prompt": prompt, "options": options or {}}, 883 ) 884 return result if isinstance(result, str) else str(result) 885 886 async def remove_background( 887 self, 888 image_data: bytes, 889 filename: str = "image.png", 890 content_type: str = "image/png", 891 ) -> str: 892 """Remove the background from an image. 893 894 Args: 895 image_data: The image file content as bytes. 896 filename: The filename (used in the multipart upload). 897 content_type: The MIME type of the image. 898 899 Returns: 900 The URL of the processed image with the background removed. 901 """ 902 result = await self._http.post_form( 903 "squid-api/v1/ai/image/removeBackground", 904 data={}, 905 files=[("file", (filename, image_data, content_type))], 906 ) 907 return result if isinstance(result, str) else str(result)
Image generation and processing.
Supports DALL-E, Stable Diffusion Core, and Flux models.
Obtained via AiClient.image().
Example::
image_url = (
await squid.ai()
.image()
.generate(
"a cat astronaut on the moon",
options={"modelName": "gpt-image-1", "quality": "high"},
)
)
863 async def generate( 864 self, 865 prompt: str, 866 options: ImageGenerateOptions | None = None, 867 ) -> str: 868 """Generate an image from a text prompt. 869 870 Args: 871 prompt: A text description of the image to generate. 872 options: Provider-specific generation options. Use one of: 873 - :class:`GptImageOptions`: ``{'modelName': 'gpt-image-1', 'quality': 'high', 'size': '1024x1024'}`` 874 - :class:`FluxOptions`: ``{'modelName': 'flux-pro-1.1', 'width': 1024, 'height': 768}`` 875 - :class:`StableDiffusionOptions`: ``{'modelName': 'stable-diffusion-core', 'aspectRatio': '16:9'}`` 876 877 Returns: 878 The URL of the generated image. 879 """ 880 result = await self._http.post( 881 "squid-api/v1/ai/image/generate", 882 {"prompt": prompt, "options": options or {}}, 883 ) 884 return result if isinstance(result, str) else str(result)
Generate an image from a text prompt.
Arguments:
- prompt: A text description of the image to generate.
- options: Provider-specific generation options. Use one of:
GptImageOptions:{'modelName': 'gpt-image-1', 'quality': 'high', 'size': '1024x1024'}FluxOptions:{'modelName': 'flux-pro-1.1', 'width': 1024, 'height': 768}StableDiffusionOptions:{'modelName': 'stable-diffusion-core', 'aspectRatio': '16:9'}
Returns:
The URL of the generated image.
886 async def remove_background( 887 self, 888 image_data: bytes, 889 filename: str = "image.png", 890 content_type: str = "image/png", 891 ) -> str: 892 """Remove the background from an image. 893 894 Args: 895 image_data: The image file content as bytes. 896 filename: The filename (used in the multipart upload). 897 content_type: The MIME type of the image. 898 899 Returns: 900 The URL of the processed image with the background removed. 901 """ 902 result = await self._http.post_form( 903 "squid-api/v1/ai/image/removeBackground", 904 data={}, 905 files=[("file", (filename, image_data, content_type))], 906 ) 907 return result if isinstance(result, str) else str(result)
Remove the background from an image.
Arguments:
- image_data: The image file content as bytes.
- filename: The filename (used in the multipart upload).
- content_type: The MIME type of the image.
Returns:
The URL of the processed image with the background removed.
435class IntegrationEmbeddingModelSpec(TypedDict): 436 """Specifies an embedding model from a specific integration.""" 437 438 integrationId: str 439 """The ID of the integration providing the embedding model.""" 440 model: str 441 """The model name as recognized by the provider.""" 442 dimensions: int 443 """The number of dimensions in the embedding vector output."""
Specifies an embedding model from a specific integration.
31class IntegrationModelSpec(TypedDict): 32 """Specifies a model from a specific integration.""" 33 34 integrationId: str 35 model: str
Specifies a model from a specific integration.
451class KnowledgeBaseClient: 452 """Operations on a single knowledge base. 453 454 Provides methods for managing knowledge base configuration, upserting 455 and searching text/file contexts, and retrieving individual contexts. 456 457 Obtained via :meth:`AiClient.knowledge_base`. 458 459 Example:: 460 461 kb = squid.ai().knowledge_base("my-kb") 462 await kb.upsert(description="Product documentation") 463 await kb.upsert_contexts( 464 [ 465 { 466 "contextId": "doc-1", 467 "type": "text", 468 "title": "Getting Started", 469 "text": "Welcome to our product...", 470 } 471 ] 472 ) 473 results = await kb.search("How do I get started?") 474 """ 475 476 def __init__(self, http: HttpTransport, kb_id: str) -> None: 477 self._http = http 478 self._kb_id = kb_id 479 480 async def get(self) -> dict | None: 481 """Get the knowledge base details. 482 483 Returns: 484 An ``AiKnowledgeBase`` dict with keys: ``id``, ``appId``, 485 ``description``, ``metadataFields``, ``embeddingModel``, 486 ``chatModel``, ``updatedAt``. Returns ``None`` if not found. 487 """ 488 return await self._http.get(f"squid-api/v1/ai/knowledge-base/get/{self._kb_id}") 489 490 async def upsert( 491 self, 492 *, 493 description: str | None = None, 494 metadata_fields: list[AiKnowledgeBaseMetadataField] | None = None, 495 embedding_model: str | None = None, 496 chat_model: AiChatModelSelection | None = None, 497 name: str | None = None, 498 vector_db_type: VectorDbType | None = None, 499 graph_rag: AiKnowledgeBaseGraphConfig | None = None, 500 ) -> None: 501 """Create or update the knowledge base. 502 503 Args: 504 description: Description of the knowledge base's content. 505 metadata_fields: Schema for metadata fields used in filtering. 506 Each field: ``{'name': str, 'dataType': str, 'required': bool, 'description'?: str}``. 507 embedding_model: The embedding model name for vectorization. 508 Required when creating a new knowledge base. 509 chat_model: The LLM model for answering questions over this KB. 510 name: Display name for the knowledge base. 511 vector_db_type: The vector store backend. Set at creation (defaulting to the 512 server's default) and immutable thereafter. The knowledge graph requires 513 ``'mongoAtlas'``. 514 graph_rag: Opt-in GraphRAG configuration (``{'enabled': True, ...}``). Only 515 honored on ``'mongoAtlas'`` knowledge bases; mutable, unlike 516 ``vector_db_type``. The value replaces the stored config rather than 517 merging into it. See :class:`AiKnowledgeBaseGraphConfig`. 518 """ 519 kb: dict[str, Any] = {"id": self._kb_id} 520 if description is not None: 521 kb["description"] = description 522 if metadata_fields is not None: 523 kb["metadataFields"] = metadata_fields 524 if embedding_model is not None: 525 kb["embeddingModel"] = embedding_model 526 if chat_model is not None: 527 kb["chatModel"] = chat_model 528 if name is not None: 529 kb["name"] = name 530 if vector_db_type is not None: 531 kb["vectorDbType"] = vector_db_type 532 if graph_rag is not None: 533 kb["graphRag"] = graph_rag 534 await self._http.post("squid-api/v1/ai/knowledge-base/upsert", {"knowledgeBase": kb}) 535 536 async def delete(self) -> None: 537 """Delete the knowledge base and all its contexts permanently.""" 538 await self._http.post("squid-api/v1/ai/knowledge-base/delete", {"id": self._kb_id}) 539 540 # --- Contexts --- 541 542 async def get_context(self, context_id: str) -> dict | None: 543 """Get a specific context entry. 544 545 Args: 546 context_id: The unique context identifier. 547 548 Returns: 549 An ``AiKnowledgeBaseContext`` dict with keys: ``id``, ``appId``, 550 ``knowledgeBaseId``, ``createdAt``, ``updatedAt``, ``type``, 551 ``title``, ``text``, ``preview``, ``sizeBytes``, ``metadata``, 552 ``requestConfig``. Returns ``None`` if not found. 553 """ 554 return await self._http.get( 555 f"squid-api/v1/ai/knowledge-base/getContext/{self._kb_id}/{context_id}" 556 ) 557 558 async def list_contexts(self) -> list[dict]: 559 """List all contexts in the knowledge base. 560 561 Deprecated: fetches every context in one call with no pagination — expensive for large 562 knowledge bases. Use :meth:`list_contexts_page` instead, which supports 563 ``offset``/``limit``/``search``. 564 565 Returns: 566 A list of ``AiKnowledgeBaseContext`` dicts. 567 """ 568 result = await self._http.get(f"squid-api/v1/ai/knowledge-base/listContexts/{self._kb_id}") 569 return result.get("contexts", []) if result else [] 570 571 async def list_contexts_page( 572 self, 573 *, 574 offset: int | None = None, 575 limit: int | None = None, 576 search: str | None = None, 577 ) -> dict: 578 """List a page of contexts in the knowledge base. 579 580 Args: 581 offset: The number of contexts to skip, for pagination. 582 limit: The maximum number of contexts to return, for pagination. 583 search: Case-insensitive substring search across id/title only. 584 585 Returns: 586 A dict with ``contexts`` (a list of ``AiKnowledgeBaseContext`` dicts for the 587 requested page) and ``totalCount`` (the total number of contexts in the 588 knowledge base, ignoring ``offset``/``limit``). 589 """ 590 params = { 591 key: str(value) 592 for key, value in {"offset": offset, "limit": limit, "search": search}.items() 593 if value is not None 594 } 595 result = await self._http.get( 596 f"squid-api/v1/ai/knowledge-base/listContextsPage/{self._kb_id}", 597 params=params or None, 598 ) 599 return result if result else {"contexts": [], "totalCount": 0} 600 601 async def upsert_contexts( 602 self, 603 contexts: list[ContextRequest], 604 files: list[tuple[str, bytes, str]] | None = None, 605 ) -> dict: 606 """Add or update contexts in the knowledge base. 607 608 Args: 609 contexts: A list of context request objects. Each must be either: 610 - A :class:`TextContextRequest`: ``{'contextId', 'type': 'text', 'title', 'text', ...}`` 611 - A :class:`FileContextRequest`: ``{'contextId', 'type': 'file', ...}`` 612 files: For file contexts, provide the actual file data as a list of 613 ``(filename, data_bytes, content_type)`` tuples. Must match the 614 order of file contexts in the ``contexts`` list. 615 616 Returns: 617 A dict with ``failures``: a list of ``UpsertContextStatusError`` dicts 618 for any contexts that failed to upsert. 619 620 Example:: 621 622 await kb.upsert_contexts( 623 [ 624 {"contextId": "doc-1", "type": "text", "title": "FAQ", "text": "..."}, 625 {"contextId": "doc-2", "type": "file"}, 626 ], 627 files=[ 628 ("manual.pdf", pdf_bytes, "application/pdf"), 629 ], 630 ) 631 """ 632 form_data = { 633 "knowledgeBaseId": self._kb_id, 634 "contexts": json.dumps(contexts), 635 } 636 file_tuples: list[tuple[str, tuple[str, bytes, str]]] = [] 637 if files: 638 for fname, fdata, ftype in files: 639 file_tuples.append(("files", (fname, fdata, ftype))) 640 return await self._http.post_form( 641 "squid-api/v1/ai/knowledge-base/upsertContexts", 642 data=form_data, 643 files=file_tuples, 644 ) 645 646 async def delete_contexts(self, context_ids: list[str]) -> None: 647 """Delete contexts by their IDs. 648 649 Args: 650 context_ids: List of context IDs to delete. 651 """ 652 await self._http.post( 653 "squid-api/v1/ai/knowledge-base/deleteContexts", 654 {"knowledgeBaseId": self._kb_id, "contextIds": context_ids}, 655 ) 656 657 # --- Search --- 658 659 async def search( 660 self, 661 prompt: str, 662 options: KnowledgeBaseSearchOptions | None = None, 663 ) -> list[dict]: 664 """Search the knowledge base using semantic search. 665 666 Args: 667 prompt: The search query in natural language. 668 options: Search options. See :class:`KnowledgeBaseSearchOptions`. 669 Supports: ``limit``, ``chunkLimit``, ``rerankProvider``, ``chatModel``, 670 ``searchMode``, ``graphOptions``, ``graphFilter``. 671 672 Returns: 673 A list of ``AiKnowledgeBaseSearchResultChunk`` dicts, each with: 674 ``contextId``, ``data``, ``metadata``, ``score``. 675 676 Example:: 677 678 chunks = await kb.search( 679 "How do I reset my password?", 680 options={ 681 "limit": 5, 682 "chatModel": "gemini-3-flash", 683 }, 684 ) 685 for chunk in chunks: 686 print(f"Score: {chunk['score']}, Data: {chunk['data'][:100]}") 687 """ 688 response = await self.search_with_graph_context(prompt, options) 689 return response.get("chunks", []) 690 691 # --- Knowledge graph --- 692 693 async def search_with_graph_context( 694 self, 695 prompt: str, 696 options: KnowledgeBaseSearchOptions | None = None, 697 ) -> dict: 698 """Like :meth:`search`, but return the full search response instead of only the chunks. 699 700 With ``searchMode: 'graph'`` and ``graphOptions: {'includeGraphContext': True}`` the 701 response also carries ``graphContext``, the subgraph the search traversed. 702 703 Args: 704 prompt: The search query in natural language. 705 options: Search options. See :class:`KnowledgeBaseSearchOptions`. 706 707 Returns: 708 An ``AiKnowledgeBaseSearchResponse`` dict: ``chunks`` (list of result chunk dicts) 709 and, when requested via ``includeGraphContext``, ``graphContext`` 710 (``{'entities': [...], 'relationships': [...]}``). 711 """ 712 search_options: dict[str, Any] = {"prompt": prompt, **(options or {})} 713 result = await self._http.post( 714 "squid-api/v1/ai/knowledge-base/search", 715 { 716 "knowledgeBaseId": self._kb_id, 717 "prompt": prompt, 718 "options": search_options, 719 }, 720 ) 721 return result or {"chunks": []} 722 723 async def get_graph_status(self) -> dict: 724 """Get the knowledge base's graph build/readiness status. 725 726 Returns: 727 A ``GetKnowledgeBaseGraphStatusResponse`` dict with ``enabled``, ``entityCount``, 728 ``relationshipCount``, ``contextsIndexed``, ``contextsTotal``, and, where available, 729 ``facets``, ``topics``, ``structureStale``, LLM usage fields, and ``buildJob`` 730 (``{'status': 'in_progress' | 'completed' | 'failed', ...}``) for the most recent 731 rebuild. Poll it after :meth:`rebuild_graph` until ``buildJob`` leaves 732 ``'in_progress'``. 733 """ 734 return await self._http.get(f"squid-api/v1/ai/knowledge-base/getGraphStatus/{self._kb_id}") 735 736 async def rebuild_graph(self, *, mode: Literal["full", "structural"] | None = None) -> None: 737 """Enqueue a graph rebuild/backfill. Requires ``graphRag.enabled``. 738 739 Only one rebuild can run per knowledge base at a time; track progress via 740 :meth:`get_graph_status`. 741 742 Args: 743 mode: ``'structural'`` (the default) keeps the already-extracted entity graph and 744 rebuilds just the concept layer; ``'full'`` wipes the graph and re-extracts every 745 context with an LLM — expensive, and only needed when the extraction itself must 746 be redone (e.g. after changing ``entityTypes`` or ``extractionModel``). 747 """ 748 request: dict[str, Any] = {"knowledgeBaseId": self._kb_id} 749 if mode is not None: 750 request["mode"] = mode 751 await self._http.post("squid-api/v1/ai/knowledge-base/rebuildGraph", request) 752 753 async def query_graph( 754 self, 755 op: KnowledgeBaseGraphQueryOp, 756 *, 757 ref: str | None = None, 758 ref_b: str | None = None, 759 context_id: str | None = None, 760 query: str | None = None, 761 depth: int | None = None, 762 hops: int | None = None, 763 recursive: bool | None = None, 764 limit: int | None = None, 765 ) -> dict: 766 """Query the knowledge base's graph (documents, entities, themes, facets). 767 768 Requires ``graphRag.enabled`` on the knowledge base. 769 770 Args: 771 op: The operation to run. 772 ref: Node ref (name or facet nodeId). Required by resolve/describe/subtree/ 773 docsUnder/neighborhood/pathBetween. 774 ref_b: Second node ref for ``pathBetween``. 775 context_id: The document's contextId for ``conceptsOf``. 776 query: The free-text question for ``globalSummary``. 777 depth: ``subtree``: maximum depth below the resolved node. Default (and cap) 3. 778 hops: ``neighborhood``: expansion hops from the resolved entity. Default 1, max 2. 779 recursive: ``docsUnder``: when True (the default), include documents under the whole 780 subtree, not just the node itself. 781 limit: ``docsUnder``: maximum documents returned. Default 25, max 100. 782 783 Returns: 784 A ``QueryKnowledgeBaseGraphResponse`` dict; which keys are present depends on ``op`` 785 (e.g. ``overview`` for 'overview', ``matches`` for 'resolve', ``node``/``path``/ 786 ``related`` for 'describe', ``tree``, ``documents``/``totalDocs``, ``concepts``, 787 ``graph``, ``pathBetween``, ``summaries``). 788 """ 789 request: dict[str, Any] = {"knowledgeBaseId": self._kb_id, "op": op} 790 if ref is not None: 791 request["ref"] = ref 792 if ref_b is not None: 793 request["refB"] = ref_b 794 if context_id is not None: 795 request["contextId"] = context_id 796 if query is not None: 797 request["query"] = query 798 if depth is not None: 799 request["depth"] = depth 800 if hops is not None: 801 request["hops"] = hops 802 if recursive is not None: 803 request["recursive"] = recursive 804 if limit is not None: 805 request["limit"] = limit 806 return await self._http.post("squid-api/v1/ai/knowledge-base/queryGraph", request) 807 808 async def explore_graph( 809 self, 810 *, 811 node_limit: int | None = None, 812 topic_id: str | None = None, 813 ) -> dict: 814 """Get a bounded slice of the knowledge base's entity graph for exploration/visualization. 815 816 Returns the highest-degree entities and the relationships among them. Requires 817 ``graphRag.enabled``. 818 819 Args: 820 node_limit: Hard cap on returned nodes. Default 200, max 1000. 821 topic_id: Restricts the subgraph to entities under the given topic node id. Ids come 822 from :meth:`get_graph_status`'s ``topics`` and churn on rebuild. 823 824 Returns: 825 An ``ExploreKnowledgeBaseGraphResponse`` dict: ``nodes``, ``edges``, and, once the 826 concept layer has been built, ``topics``. 827 """ 828 request: dict[str, Any] = {"knowledgeBaseId": self._kb_id} 829 if node_limit is not None: 830 request["nodeLimit"] = node_limit 831 if topic_id is not None: 832 request["topicId"] = topic_id 833 return await self._http.post("squid-api/v1/ai/knowledge-base/exploreGraph", request)
Operations on a single knowledge base.
Provides methods for managing knowledge base configuration, upserting and searching text/file contexts, and retrieving individual contexts.
Obtained via AiClient.knowledge_base().
Example::
kb = squid.ai().knowledge_base("my-kb")
await kb.upsert(description="Product documentation")
await kb.upsert_contexts(
[
{
"contextId": "doc-1",
"type": "text",
"title": "Getting Started",
"text": "Welcome to our product...",
}
]
)
results = await kb.search("How do I get started?")
480 async def get(self) -> dict | None: 481 """Get the knowledge base details. 482 483 Returns: 484 An ``AiKnowledgeBase`` dict with keys: ``id``, ``appId``, 485 ``description``, ``metadataFields``, ``embeddingModel``, 486 ``chatModel``, ``updatedAt``. Returns ``None`` if not found. 487 """ 488 return await self._http.get(f"squid-api/v1/ai/knowledge-base/get/{self._kb_id}")
Get the knowledge base details.
Returns:
An
AiKnowledgeBasedict with keys:id,appId,description,metadataFields,embeddingModel,chatModel,updatedAt. ReturnsNoneif not found.
490 async def upsert( 491 self, 492 *, 493 description: str | None = None, 494 metadata_fields: list[AiKnowledgeBaseMetadataField] | None = None, 495 embedding_model: str | None = None, 496 chat_model: AiChatModelSelection | None = None, 497 name: str | None = None, 498 vector_db_type: VectorDbType | None = None, 499 graph_rag: AiKnowledgeBaseGraphConfig | None = None, 500 ) -> None: 501 """Create or update the knowledge base. 502 503 Args: 504 description: Description of the knowledge base's content. 505 metadata_fields: Schema for metadata fields used in filtering. 506 Each field: ``{'name': str, 'dataType': str, 'required': bool, 'description'?: str}``. 507 embedding_model: The embedding model name for vectorization. 508 Required when creating a new knowledge base. 509 chat_model: The LLM model for answering questions over this KB. 510 name: Display name for the knowledge base. 511 vector_db_type: The vector store backend. Set at creation (defaulting to the 512 server's default) and immutable thereafter. The knowledge graph requires 513 ``'mongoAtlas'``. 514 graph_rag: Opt-in GraphRAG configuration (``{'enabled': True, ...}``). Only 515 honored on ``'mongoAtlas'`` knowledge bases; mutable, unlike 516 ``vector_db_type``. The value replaces the stored config rather than 517 merging into it. See :class:`AiKnowledgeBaseGraphConfig`. 518 """ 519 kb: dict[str, Any] = {"id": self._kb_id} 520 if description is not None: 521 kb["description"] = description 522 if metadata_fields is not None: 523 kb["metadataFields"] = metadata_fields 524 if embedding_model is not None: 525 kb["embeddingModel"] = embedding_model 526 if chat_model is not None: 527 kb["chatModel"] = chat_model 528 if name is not None: 529 kb["name"] = name 530 if vector_db_type is not None: 531 kb["vectorDbType"] = vector_db_type 532 if graph_rag is not None: 533 kb["graphRag"] = graph_rag 534 await self._http.post("squid-api/v1/ai/knowledge-base/upsert", {"knowledgeBase": kb})
Create or update the knowledge base.
Arguments:
- description: Description of the knowledge base's content.
- metadata_fields: Schema for metadata fields used in filtering.
Each field:
{'name': str, 'dataType': str, 'required': bool, 'description'?: str}. - embedding_model: The embedding model name for vectorization. Required when creating a new knowledge base.
- chat_model: The LLM model for answering questions over this KB.
- name: Display name for the knowledge base.
- vector_db_type: The vector store backend. Set at creation (defaulting to the
server's default) and immutable thereafter. The knowledge graph requires
'mongoAtlas'. - graph_rag: Opt-in GraphRAG configuration (
{'enabled': True, ...}). Only honored on'mongoAtlas'knowledge bases; mutable, unlikevector_db_type. The value replaces the stored config rather than merging into it. SeeAiKnowledgeBaseGraphConfig.
536 async def delete(self) -> None: 537 """Delete the knowledge base and all its contexts permanently.""" 538 await self._http.post("squid-api/v1/ai/knowledge-base/delete", {"id": self._kb_id})
Delete the knowledge base and all its contexts permanently.
542 async def get_context(self, context_id: str) -> dict | None: 543 """Get a specific context entry. 544 545 Args: 546 context_id: The unique context identifier. 547 548 Returns: 549 An ``AiKnowledgeBaseContext`` dict with keys: ``id``, ``appId``, 550 ``knowledgeBaseId``, ``createdAt``, ``updatedAt``, ``type``, 551 ``title``, ``text``, ``preview``, ``sizeBytes``, ``metadata``, 552 ``requestConfig``. Returns ``None`` if not found. 553 """ 554 return await self._http.get( 555 f"squid-api/v1/ai/knowledge-base/getContext/{self._kb_id}/{context_id}" 556 )
Get a specific context entry.
Arguments:
- context_id: The unique context identifier.
Returns:
An
AiKnowledgeBaseContextdict with keys:id,appId,knowledgeBaseId,createdAt,updatedAt,type,title,text,preview,sizeBytes,metadata,requestConfig. ReturnsNoneif not found.
558 async def list_contexts(self) -> list[dict]: 559 """List all contexts in the knowledge base. 560 561 Deprecated: fetches every context in one call with no pagination — expensive for large 562 knowledge bases. Use :meth:`list_contexts_page` instead, which supports 563 ``offset``/``limit``/``search``. 564 565 Returns: 566 A list of ``AiKnowledgeBaseContext`` dicts. 567 """ 568 result = await self._http.get(f"squid-api/v1/ai/knowledge-base/listContexts/{self._kb_id}") 569 return result.get("contexts", []) if result else []
List all contexts in the knowledge base.
Deprecated: fetches every context in one call with no pagination — expensive for large
knowledge bases. Use list_contexts_page() instead, which supports
offset/limit/search.
Returns:
A list of
AiKnowledgeBaseContextdicts.
571 async def list_contexts_page( 572 self, 573 *, 574 offset: int | None = None, 575 limit: int | None = None, 576 search: str | None = None, 577 ) -> dict: 578 """List a page of contexts in the knowledge base. 579 580 Args: 581 offset: The number of contexts to skip, for pagination. 582 limit: The maximum number of contexts to return, for pagination. 583 search: Case-insensitive substring search across id/title only. 584 585 Returns: 586 A dict with ``contexts`` (a list of ``AiKnowledgeBaseContext`` dicts for the 587 requested page) and ``totalCount`` (the total number of contexts in the 588 knowledge base, ignoring ``offset``/``limit``). 589 """ 590 params = { 591 key: str(value) 592 for key, value in {"offset": offset, "limit": limit, "search": search}.items() 593 if value is not None 594 } 595 result = await self._http.get( 596 f"squid-api/v1/ai/knowledge-base/listContextsPage/{self._kb_id}", 597 params=params or None, 598 ) 599 return result if result else {"contexts": [], "totalCount": 0}
List a page of contexts in the knowledge base.
Arguments:
- offset: The number of contexts to skip, for pagination.
- limit: The maximum number of contexts to return, for pagination.
- search: Case-insensitive substring search across id/title only.
Returns:
A dict with
contexts(a list ofAiKnowledgeBaseContextdicts for the requested page) andtotalCount(the total number of contexts in the knowledge base, ignoringoffset/limit).
601 async def upsert_contexts( 602 self, 603 contexts: list[ContextRequest], 604 files: list[tuple[str, bytes, str]] | None = None, 605 ) -> dict: 606 """Add or update contexts in the knowledge base. 607 608 Args: 609 contexts: A list of context request objects. Each must be either: 610 - A :class:`TextContextRequest`: ``{'contextId', 'type': 'text', 'title', 'text', ...}`` 611 - A :class:`FileContextRequest`: ``{'contextId', 'type': 'file', ...}`` 612 files: For file contexts, provide the actual file data as a list of 613 ``(filename, data_bytes, content_type)`` tuples. Must match the 614 order of file contexts in the ``contexts`` list. 615 616 Returns: 617 A dict with ``failures``: a list of ``UpsertContextStatusError`` dicts 618 for any contexts that failed to upsert. 619 620 Example:: 621 622 await kb.upsert_contexts( 623 [ 624 {"contextId": "doc-1", "type": "text", "title": "FAQ", "text": "..."}, 625 {"contextId": "doc-2", "type": "file"}, 626 ], 627 files=[ 628 ("manual.pdf", pdf_bytes, "application/pdf"), 629 ], 630 ) 631 """ 632 form_data = { 633 "knowledgeBaseId": self._kb_id, 634 "contexts": json.dumps(contexts), 635 } 636 file_tuples: list[tuple[str, tuple[str, bytes, str]]] = [] 637 if files: 638 for fname, fdata, ftype in files: 639 file_tuples.append(("files", (fname, fdata, ftype))) 640 return await self._http.post_form( 641 "squid-api/v1/ai/knowledge-base/upsertContexts", 642 data=form_data, 643 files=file_tuples, 644 )
Add or update contexts in the knowledge base.
Arguments:
- contexts: A list of context request objects. Each must be either:
- A
TextContextRequest:{'contextId', 'type': 'text', 'title', 'text', ...} - A
FileContextRequest:{'contextId', 'type': 'file', ...}
- A
- files: For file contexts, provide the actual file data as a list of
(filename, data_bytes, content_type)tuples. Must match the order of file contexts in thecontextslist.
Returns:
A dict with
failures: a list ofUpsertContextStatusErrordicts for any contexts that failed to upsert.
Example::
await kb.upsert_contexts(
[
{"contextId": "doc-1", "type": "text", "title": "FAQ", "text": "..."},
{"contextId": "doc-2", "type": "file"},
],
files=[
("manual.pdf", pdf_bytes, "application/pdf"),
],
)
646 async def delete_contexts(self, context_ids: list[str]) -> None: 647 """Delete contexts by their IDs. 648 649 Args: 650 context_ids: List of context IDs to delete. 651 """ 652 await self._http.post( 653 "squid-api/v1/ai/knowledge-base/deleteContexts", 654 {"knowledgeBaseId": self._kb_id, "contextIds": context_ids}, 655 )
Delete contexts by their IDs.
Arguments:
- context_ids: List of context IDs to delete.
659 async def search( 660 self, 661 prompt: str, 662 options: KnowledgeBaseSearchOptions | None = None, 663 ) -> list[dict]: 664 """Search the knowledge base using semantic search. 665 666 Args: 667 prompt: The search query in natural language. 668 options: Search options. See :class:`KnowledgeBaseSearchOptions`. 669 Supports: ``limit``, ``chunkLimit``, ``rerankProvider``, ``chatModel``, 670 ``searchMode``, ``graphOptions``, ``graphFilter``. 671 672 Returns: 673 A list of ``AiKnowledgeBaseSearchResultChunk`` dicts, each with: 674 ``contextId``, ``data``, ``metadata``, ``score``. 675 676 Example:: 677 678 chunks = await kb.search( 679 "How do I reset my password?", 680 options={ 681 "limit": 5, 682 "chatModel": "gemini-3-flash", 683 }, 684 ) 685 for chunk in chunks: 686 print(f"Score: {chunk['score']}, Data: {chunk['data'][:100]}") 687 """ 688 response = await self.search_with_graph_context(prompt, options) 689 return response.get("chunks", [])
Search the knowledge base using semantic search.
Arguments:
- prompt: The search query in natural language.
- options: Search options. See
KnowledgeBaseSearchOptions. Supports:limit,chunkLimit,rerankProvider,chatModel,searchMode,graphOptions,graphFilter.
Returns:
A list of
AiKnowledgeBaseSearchResultChunkdicts, each with:contextId,data,metadata,score.
Example::
chunks = await kb.search(
"How do I reset my password?",
options={
"limit": 5,
"chatModel": "gemini-3-flash",
},
)
for chunk in chunks:
print(f"Score: {chunk['score']}, Data: {chunk['data'][:100]}")
693 async def search_with_graph_context( 694 self, 695 prompt: str, 696 options: KnowledgeBaseSearchOptions | None = None, 697 ) -> dict: 698 """Like :meth:`search`, but return the full search response instead of only the chunks. 699 700 With ``searchMode: 'graph'`` and ``graphOptions: {'includeGraphContext': True}`` the 701 response also carries ``graphContext``, the subgraph the search traversed. 702 703 Args: 704 prompt: The search query in natural language. 705 options: Search options. See :class:`KnowledgeBaseSearchOptions`. 706 707 Returns: 708 An ``AiKnowledgeBaseSearchResponse`` dict: ``chunks`` (list of result chunk dicts) 709 and, when requested via ``includeGraphContext``, ``graphContext`` 710 (``{'entities': [...], 'relationships': [...]}``). 711 """ 712 search_options: dict[str, Any] = {"prompt": prompt, **(options or {})} 713 result = await self._http.post( 714 "squid-api/v1/ai/knowledge-base/search", 715 { 716 "knowledgeBaseId": self._kb_id, 717 "prompt": prompt, 718 "options": search_options, 719 }, 720 ) 721 return result or {"chunks": []}
Like search(), but return the full search response instead of only the chunks.
With searchMode: 'graph' and graphOptions: {'includeGraphContext': True} the
response also carries graphContext, the subgraph the search traversed.
Arguments:
- prompt: The search query in natural language.
- options: Search options. See
KnowledgeBaseSearchOptions.
Returns:
An
AiKnowledgeBaseSearchResponsedict:chunks(list of result chunk dicts) and, when requested viaincludeGraphContext,graphContext({'entities': [...], 'relationships': [...]}).
723 async def get_graph_status(self) -> dict: 724 """Get the knowledge base's graph build/readiness status. 725 726 Returns: 727 A ``GetKnowledgeBaseGraphStatusResponse`` dict with ``enabled``, ``entityCount``, 728 ``relationshipCount``, ``contextsIndexed``, ``contextsTotal``, and, where available, 729 ``facets``, ``topics``, ``structureStale``, LLM usage fields, and ``buildJob`` 730 (``{'status': 'in_progress' | 'completed' | 'failed', ...}``) for the most recent 731 rebuild. Poll it after :meth:`rebuild_graph` until ``buildJob`` leaves 732 ``'in_progress'``. 733 """ 734 return await self._http.get(f"squid-api/v1/ai/knowledge-base/getGraphStatus/{self._kb_id}")
Get the knowledge base's graph build/readiness status.
Returns:
A
GetKnowledgeBaseGraphStatusResponsedict withenabled,entityCount,relationshipCount,contextsIndexed,contextsTotal, and, where available,facets,topics,structureStale, LLM usage fields, andbuildJob({'status': 'in_progress' | 'completed' | 'failed', ...}) for the most recent rebuild. Poll it afterrebuild_graph()untilbuildJobleaves'in_progress'.
736 async def rebuild_graph(self, *, mode: Literal["full", "structural"] | None = None) -> None: 737 """Enqueue a graph rebuild/backfill. Requires ``graphRag.enabled``. 738 739 Only one rebuild can run per knowledge base at a time; track progress via 740 :meth:`get_graph_status`. 741 742 Args: 743 mode: ``'structural'`` (the default) keeps the already-extracted entity graph and 744 rebuilds just the concept layer; ``'full'`` wipes the graph and re-extracts every 745 context with an LLM — expensive, and only needed when the extraction itself must 746 be redone (e.g. after changing ``entityTypes`` or ``extractionModel``). 747 """ 748 request: dict[str, Any] = {"knowledgeBaseId": self._kb_id} 749 if mode is not None: 750 request["mode"] = mode 751 await self._http.post("squid-api/v1/ai/knowledge-base/rebuildGraph", request)
Enqueue a graph rebuild/backfill. Requires graphRag.enabled.
Only one rebuild can run per knowledge base at a time; track progress via
get_graph_status().
Arguments:
- mode:
'structural'(the default) keeps the already-extracted entity graph and rebuilds just the concept layer;'full'wipes the graph and re-extracts every context with an LLM — expensive, and only needed when the extraction itself must be redone (e.g. after changingentityTypesorextractionModel).
753 async def query_graph( 754 self, 755 op: KnowledgeBaseGraphQueryOp, 756 *, 757 ref: str | None = None, 758 ref_b: str | None = None, 759 context_id: str | None = None, 760 query: str | None = None, 761 depth: int | None = None, 762 hops: int | None = None, 763 recursive: bool | None = None, 764 limit: int | None = None, 765 ) -> dict: 766 """Query the knowledge base's graph (documents, entities, themes, facets). 767 768 Requires ``graphRag.enabled`` on the knowledge base. 769 770 Args: 771 op: The operation to run. 772 ref: Node ref (name or facet nodeId). Required by resolve/describe/subtree/ 773 docsUnder/neighborhood/pathBetween. 774 ref_b: Second node ref for ``pathBetween``. 775 context_id: The document's contextId for ``conceptsOf``. 776 query: The free-text question for ``globalSummary``. 777 depth: ``subtree``: maximum depth below the resolved node. Default (and cap) 3. 778 hops: ``neighborhood``: expansion hops from the resolved entity. Default 1, max 2. 779 recursive: ``docsUnder``: when True (the default), include documents under the whole 780 subtree, not just the node itself. 781 limit: ``docsUnder``: maximum documents returned. Default 25, max 100. 782 783 Returns: 784 A ``QueryKnowledgeBaseGraphResponse`` dict; which keys are present depends on ``op`` 785 (e.g. ``overview`` for 'overview', ``matches`` for 'resolve', ``node``/``path``/ 786 ``related`` for 'describe', ``tree``, ``documents``/``totalDocs``, ``concepts``, 787 ``graph``, ``pathBetween``, ``summaries``). 788 """ 789 request: dict[str, Any] = {"knowledgeBaseId": self._kb_id, "op": op} 790 if ref is not None: 791 request["ref"] = ref 792 if ref_b is not None: 793 request["refB"] = ref_b 794 if context_id is not None: 795 request["contextId"] = context_id 796 if query is not None: 797 request["query"] = query 798 if depth is not None: 799 request["depth"] = depth 800 if hops is not None: 801 request["hops"] = hops 802 if recursive is not None: 803 request["recursive"] = recursive 804 if limit is not None: 805 request["limit"] = limit 806 return await self._http.post("squid-api/v1/ai/knowledge-base/queryGraph", request)
Query the knowledge base's graph (documents, entities, themes, facets).
Requires graphRag.enabled on the knowledge base.
Arguments:
- op: The operation to run.
- ref: Node ref (name or facet nodeId). Required by resolve/describe/subtree/ docsUnder/neighborhood/pathBetween.
- ref_b: Second node ref for
pathBetween. - context_id: The document's contextId for
conceptsOf. - query: The free-text question for
globalSummary. - depth:
subtree: maximum depth below the resolved node. Default (and cap) 3. - hops:
neighborhood: expansion hops from the resolved entity. Default 1, max 2. - recursive:
docsUnder: when True (the default), include documents under the whole subtree, not just the node itself. - limit:
docsUnder: maximum documents returned. Default 25, max 100.
Returns:
A
QueryKnowledgeBaseGraphResponsedict; which keys are present depends onop(e.g.overviewfor 'overview',matchesfor 'resolve',node/path/relatedfor 'describe',tree,documents/totalDocs,concepts,graph,pathBetween,summaries).
808 async def explore_graph( 809 self, 810 *, 811 node_limit: int | None = None, 812 topic_id: str | None = None, 813 ) -> dict: 814 """Get a bounded slice of the knowledge base's entity graph for exploration/visualization. 815 816 Returns the highest-degree entities and the relationships among them. Requires 817 ``graphRag.enabled``. 818 819 Args: 820 node_limit: Hard cap on returned nodes. Default 200, max 1000. 821 topic_id: Restricts the subgraph to entities under the given topic node id. Ids come 822 from :meth:`get_graph_status`'s ``topics`` and churn on rebuild. 823 824 Returns: 825 An ``ExploreKnowledgeBaseGraphResponse`` dict: ``nodes``, ``edges``, and, once the 826 concept layer has been built, ``topics``. 827 """ 828 request: dict[str, Any] = {"knowledgeBaseId": self._kb_id} 829 if node_limit is not None: 830 request["nodeLimit"] = node_limit 831 if topic_id is not None: 832 request["topicId"] = topic_id 833 return await self._http.post("squid-api/v1/ai/knowledge-base/exploreGraph", request)
Get a bounded slice of the knowledge base's entity graph for exploration/visualization.
Returns the highest-degree entities and the relationships among them. Requires
graphRag.enabled.
Arguments:
- node_limit: Hard cap on returned nodes. Default 200, max 1000.
- topic_id: Restricts the subgraph to entities under the given topic node id. Ids come
from
get_graph_status()'stopicsand churn on rebuild.
Returns:
An
ExploreKnowledgeBaseGraphResponsedict:nodes,edges, and, once the concept layer has been built,topics.
643class KnowledgeBaseSearchOptions(TypedDict, total=False): 644 """Options for knowledge base search.""" 645 646 prompt: str 647 """The search prompt.""" 648 limit: int 649 """Max number of results to return.""" 650 chunkLimit: int 651 """How many chunks to search over (default 100).""" 652 rerankProvider: AiRerankProvider 653 """Reranker provider (default 'cohere').""" 654 chatModel: AiChatModelSelection 655 """Model to use for answering.""" 656 searchMode: Literal["vector", "hybrid", "keyword", "graph"] 657 """Retrieval mode: 'hybrid' (BM25+dense fusion where supported; default on non-graph KBs), 658 'vector' (dense only), 'keyword' (pure lexical — every whitespace-separated term must appear 659 as a literal, case-insensitive substring), or 'graph' (GraphRAG — seeds entities via vector 660 search, expands relationships via graph traversal, maps entities back to their chunks, fused 661 with a hybrid search; requires a ``vectorDbType: 'mongoAtlas'`` KB with ``graphRag.enabled`` 662 and is the default there).""" 663 graphOptions: AiKnowledgeBaseGraphSearchOptions 664 """Tuning for ``searchMode: 'graph'``. Ignored for other search modes.""" 665 graphFilter: AiKnowledgeBaseGraphFilter 666 """Scopes the search to the documents under one concept of the KB's graph. Requires 667 ``graphRag.enabled``."""
Options for knowledge base search.
Retrieval mode: 'hybrid' (BM25+dense fusion where supported; default on non-graph KBs),
'vector' (dense only), 'keyword' (pure lexical — every whitespace-separated term must appear
as a literal, case-insensitive substring), or 'graph' (GraphRAG — seeds entities via vector
search, expands relationships via graph traversal, maps entities back to their chunks, fused
with a hybrid search; requires a vectorDbType: 'mongoAtlas' KB with graphRag.enabled
and is the default there).
Tuning for searchMode: 'graph'. Ignored for other search modes.
Scopes the search to the documents under one concept of the KB's graph. Requires
graphRag.enabled.
21class MatchmakingClient: 22 """AI-powered matchmaking: match makers, entities, matching.""" 23 24 def __init__(self, http: HttpTransport) -> None: 25 self._http = http 26 27 # --- Match makers --- 28 29 async def create_match_maker( 30 self, 31 match_maker_id: str, 32 description: str, 33 categories: list[MmCategory], 34 ) -> dict: 35 """Create a new match maker.""" 36 return await self._http.post( 37 "squid-api/v1/ai/matchmaking/createMatchMaker", 38 {"id": match_maker_id, "description": description, "categories": categories}, 39 ) 40 41 async def get_match_maker(self, match_maker_id: str) -> dict | None: 42 """Get a match maker by ID.""" 43 result = await self._http.get(f"squid-api/v1/ai/matchmaking/getMatchMaker/{match_maker_id}") 44 return result.get("matchMaker") if result else None 45 46 async def list_match_makers(self) -> list[dict]: 47 """List all match makers.""" 48 result = await self._http.get("squid-api/v1/ai/matchmaking/listMatchMakers") 49 return result.get("matchMakers", []) if result else [] 50 51 async def delete_match_maker(self, match_maker_id: str) -> None: 52 """Delete a match maker.""" 53 await self._http.post( 54 "squid-api/v1/ai/matchmaking/deleteMatchMaker", 55 {"matchMakerId": match_maker_id}, 56 ) 57 58 # --- Entities --- 59 60 async def insert_entities(self, match_maker_id: str, entities: list[MmEntity]) -> None: 61 """Insert entities into a match maker.""" 62 await self._http.post( 63 "squid-api/v1/ai/matchmaking/insertEntities", 64 {"matchMakerId": match_maker_id, "entities": entities}, 65 ) 66 67 async def delete_entity(self, match_maker_id: str, entity_id: str) -> None: 68 """Delete an entity.""" 69 await self._http.post( 70 "squid-api/v1/ai/matchmaking/deleteEntity", 71 {"matchMakerId": match_maker_id, "entityId": entity_id}, 72 ) 73 74 async def get_entity(self, match_maker_id: str, entity_id: str) -> dict | None: 75 """Get a specific entity.""" 76 result = await self._http.get( 77 f"squid-api/v1/ai/matchmaking/getEntity/{match_maker_id}/{entity_id}" 78 ) 79 return result.get("entity") if result else None 80 81 async def list_entities( 82 self, 83 match_maker_id: str, 84 category_id: str, 85 options: MmListEntitiesOptions | None = None, 86 ) -> list[dict]: 87 """List entities in a category.""" 88 result = await self._http.post( 89 "squid-api/v1/ai/matchmaking/listEntities", 90 { 91 "matchMakerId": match_maker_id, 92 "categoryId": category_id, 93 "options": options or {}, 94 }, 95 ) 96 return result.get("entities", []) if result else [] 97 98 # --- Matching --- 99 100 async def find_matches( 101 self, 102 match_maker_id: str, 103 entity_id: str, 104 options: MmFindMatchesOptions | None = None, 105 ) -> list[dict]: 106 """Find matches for an existing entity. 107 108 Returns list of MmEntityMatch dicts with: 109 id, content, categoryId, metadata, score, reasoning. 110 """ 111 result = await self._http.post( 112 "squid-api/v1/ai/matchmaking/findMatches", 113 { 114 "matchMakerId": match_maker_id, 115 "entityId": entity_id, 116 "options": options or {}, 117 }, 118 ) 119 return result.get("matches", []) if result else [] 120 121 async def find_matches_for_entity( 122 self, 123 match_maker_id: str, 124 entity: MmEntity, 125 options: MmFindMatchesOptions | None = None, 126 ) -> list[dict]: 127 """Find matches for a new entity (not yet inserted).""" 128 result = await self._http.post( 129 "squid-api/v1/ai/matchmaking/findMatchesForEntity", 130 { 131 "matchMakerId": match_maker_id, 132 "entity": entity, 133 "options": options or {}, 134 }, 135 ) 136 return result.get("matches", []) if result else []
AI-powered matchmaking: match makers, entities, matching.
29 async def create_match_maker( 30 self, 31 match_maker_id: str, 32 description: str, 33 categories: list[MmCategory], 34 ) -> dict: 35 """Create a new match maker.""" 36 return await self._http.post( 37 "squid-api/v1/ai/matchmaking/createMatchMaker", 38 {"id": match_maker_id, "description": description, "categories": categories}, 39 )
Create a new match maker.
41 async def get_match_maker(self, match_maker_id: str) -> dict | None: 42 """Get a match maker by ID.""" 43 result = await self._http.get(f"squid-api/v1/ai/matchmaking/getMatchMaker/{match_maker_id}") 44 return result.get("matchMaker") if result else None
Get a match maker by ID.
46 async def list_match_makers(self) -> list[dict]: 47 """List all match makers.""" 48 result = await self._http.get("squid-api/v1/ai/matchmaking/listMatchMakers") 49 return result.get("matchMakers", []) if result else []
List all match makers.
51 async def delete_match_maker(self, match_maker_id: str) -> None: 52 """Delete a match maker.""" 53 await self._http.post( 54 "squid-api/v1/ai/matchmaking/deleteMatchMaker", 55 {"matchMakerId": match_maker_id}, 56 )
Delete a match maker.
60 async def insert_entities(self, match_maker_id: str, entities: list[MmEntity]) -> None: 61 """Insert entities into a match maker.""" 62 await self._http.post( 63 "squid-api/v1/ai/matchmaking/insertEntities", 64 {"matchMakerId": match_maker_id, "entities": entities}, 65 )
Insert entities into a match maker.
67 async def delete_entity(self, match_maker_id: str, entity_id: str) -> None: 68 """Delete an entity.""" 69 await self._http.post( 70 "squid-api/v1/ai/matchmaking/deleteEntity", 71 {"matchMakerId": match_maker_id, "entityId": entity_id}, 72 )
Delete an entity.
74 async def get_entity(self, match_maker_id: str, entity_id: str) -> dict | None: 75 """Get a specific entity.""" 76 result = await self._http.get( 77 f"squid-api/v1/ai/matchmaking/getEntity/{match_maker_id}/{entity_id}" 78 ) 79 return result.get("entity") if result else None
Get a specific entity.
81 async def list_entities( 82 self, 83 match_maker_id: str, 84 category_id: str, 85 options: MmListEntitiesOptions | None = None, 86 ) -> list[dict]: 87 """List entities in a category.""" 88 result = await self._http.post( 89 "squid-api/v1/ai/matchmaking/listEntities", 90 { 91 "matchMakerId": match_maker_id, 92 "categoryId": category_id, 93 "options": options or {}, 94 }, 95 ) 96 return result.get("entities", []) if result else []
List entities in a category.
100 async def find_matches( 101 self, 102 match_maker_id: str, 103 entity_id: str, 104 options: MmFindMatchesOptions | None = None, 105 ) -> list[dict]: 106 """Find matches for an existing entity. 107 108 Returns list of MmEntityMatch dicts with: 109 id, content, categoryId, metadata, score, reasoning. 110 """ 111 result = await self._http.post( 112 "squid-api/v1/ai/matchmaking/findMatches", 113 { 114 "matchMakerId": match_maker_id, 115 "entityId": entity_id, 116 "options": options or {}, 117 }, 118 ) 119 return result.get("matches", []) if result else []
Find matches for an existing entity.
Returns list of MmEntityMatch dicts with: id, content, categoryId, metadata, score, reasoning.
121 async def find_matches_for_entity( 122 self, 123 match_maker_id: str, 124 entity: MmEntity, 125 options: MmFindMatchesOptions | None = None, 126 ) -> list[dict]: 127 """Find matches for a new entity (not yet inserted).""" 128 result = await self._http.post( 129 "squid-api/v1/ai/matchmaking/findMatchesForEntity", 130 { 131 "matchMakerId": match_maker_id, 132 "entity": entity, 133 "options": options or {}, 134 }, 135 ) 136 return result.get("matches", []) if result else []
Find matches for a new entity (not yet inserted).
773class MmCategory(TypedDict): 774 """Matchmaking category.""" 775 776 id: str 777 description: str
Matchmaking category.
780class MmEntity(TypedDict, total=False): 781 """Matchmaking entity.""" 782 783 id: str 784 content: str 785 categoryId: str 786 metadata: dict[str, Any]
Matchmaking entity.
789class MmFindMatchesOptions(TypedDict, total=False): 790 """Options for finding matches.""" 791 792 metadataFilter: dict[str, Any] 793 """AiContextMetadataFilter conditions.""" 794 limit: int 795 """Max matches to return (default 100, max 100).""" 796 matchToCategoryId: str 797 """Category to match against."""
Options for finding matches.
800class MmListEntitiesOptions(TypedDict, total=False): 801 """Options for listing entities.""" 802 803 metadataFilter: dict[str, Any] 804 limit: int
Options for listing entities.
45class ModelIdSpec(TypedDict, total=False): 46 """An AI chat model available to the app. 47 48 Returned by :meth:`AiClient.list_chat_models`. 49 """ 50 51 modelId: AiChatModelName 52 """The model ID used for API calls. Required.""" 53 integrationId: str 54 """The integration ID if this model comes from an integration (OpenAI-compatible, 55 Bedrock). Absent for Squid-provided models.""" 56 displayName: str 57 """Human-readable display name for the model (e.g. 'GPT-4o').""" 58 description: str 59 """Short human-readable description of the model. Absent for custom integration models.""" 60 replacedBy: AiChatModelName 61 """Set only for deprecated models: the active model that calls to this model are 62 routed to. Absent for active models.""" 63 source: AiModelSource 64 """Where the model comes from: 'vendor' (Squid-provided), 'connector' (provided by an 65 integration configured on the app), or 'custom' (user-added model from the app's bundle)."""
An AI chat model available to the app.
Returned by AiClient.list_chat_models().
The integration ID if this model comes from an integration (OpenAI-compatible, Bedrock). Absent for Squid-provided models.
Short human-readable description of the model. Absent for custom integration models.
24class Squid: 25 """Squid Cloud Python client. 26 27 The main entry point for interacting with the Squid Cloud platform. 28 Provides access to AI agents, knowledge bases, web utilities, 29 matchmaking, document extraction, backend functions, and webhooks. 30 31 Usage:: 32 33 squid = Squid( 34 app_id="my-app", 35 api_key="sk-...", 36 region="us-east-1.aws", 37 environment_id="dev", 38 ) 39 40 # AI agent 41 response = await squid.ai().agent("my-agent").ask("Hello!") 42 43 # Execute backend function 44 result = await squid.execute_function("MyService:greet", "World") 45 46 # Web search 47 results = await squid.web().ai_search("latest news") 48 49 # Cleanup 50 await squid.close() 51 52 Can also be used as an async context manager:: 53 54 async with Squid(app_id="my-app", api_key="sk-...", region="us-east-1.aws") as squid: 55 result = await squid.ai().agent("my-agent").ask("Hello!") 56 """ 57 58 def __init__( 59 self, 60 app_id: str, 61 region: str, 62 api_key: str | None = None, 63 environment_id: str | None = None, 64 squid_developer_id: str | None = None, 65 ) -> None: 66 """Initialize the Squid client. 67 68 Args: 69 app_id: The Squid application ID. 70 region: The deployment region (e.g., 'us-east-1.aws', 'local'). 71 api_key: API key for authentication. Required for most operations. 72 environment_id: Environment identifier (e.g., 'dev', 'prod'). 73 Appended to app_id as '{app_id}-{environment_id}'. 74 squid_developer_id: Developer identifier for local development. 75 Appended to app_id as '{app_id}-{environment_id}-{developer_id}'. 76 """ 77 self._app_id = app_id 78 self._region = region 79 self._environment_id = environment_id 80 self._squid_developer_id = squid_developer_id 81 82 full_app_id = app_id 83 if environment_id: 84 full_app_id = f"{app_id}-{environment_id}" 85 if squid_developer_id: 86 full_app_id = f"{full_app_id}-{squid_developer_id}" 87 88 self._full_app_id = full_app_id 89 self._http = HttpTransport( 90 app_id=full_app_id, 91 region=region, 92 api_key=api_key, 93 ) 94 95 @property 96 def app_id(self) -> str: 97 """The application ID (without environment/developer suffix).""" 98 return self._app_id 99 100 @property 101 def region(self) -> str: 102 """The deployment region.""" 103 return self._region 104 105 @property 106 def client_id(self) -> str: 107 """The unique client instance ID (UUID generated per Squid instance).""" 108 return self._http.client_id 109 110 # --- Sub-clients --- 111 112 def ai(self) -> AiClient: 113 """Access AI operations. 114 115 Provides access to AI agents, knowledge bases, image generation, 116 and audio transcription/synthesis. 117 118 Returns: 119 An :class:`AiClient` instance. 120 121 Example:: 122 123 agent = squid.ai().agent("my-agent") 124 response = await agent.ask("What is the weather?") 125 126 kb = squid.ai().knowledge_base("my-kb") 127 results = await kb.search("query") 128 """ 129 return AiClient(self._http) 130 131 def web(self) -> WebClient: 132 """Access web utilities. 133 134 Provides AI-powered web search, URL content extraction, 135 and short URL management. 136 137 Returns: 138 A :class:`WebClient` instance. 139 140 Example:: 141 142 content = await squid.web().get_url_content("https://example.com") 143 results = await squid.web().ai_search("latest AI news") 144 """ 145 return WebClient(self._http) 146 147 def matchmaking(self) -> MatchmakingClient: 148 """Access AI-powered matchmaking. 149 150 Provides match maker management, entity CRUD, 151 and AI-powered entity matching. 152 153 Returns: 154 A :class:`MatchmakingClient` instance. 155 156 Example:: 157 158 mm = squid.matchmaking() 159 await mm.create_match_maker("jobs", "Job matching", categories=[...]) 160 matches = await mm.find_matches("jobs", "entity-1") 161 """ 162 return MatchmakingClient(self._http) 163 164 def extraction(self) -> ExtractionClient: 165 """Access document extraction and PDF creation. 166 167 Provides PDF generation from HTML or URLs, and structured data 168 extraction from documents (PDF, DOCX, images, etc.). 169 170 Returns: 171 An :class:`ExtractionClient` instance. 172 173 Example:: 174 175 pdf = await squid.extraction().create_pdf_from_html("<h1>Hello</h1>") 176 data = await squid.extraction().extract_data_from_document_url( 177 "https://example.com/doc.pdf" 178 ) 179 """ 180 return ExtractionClient(self._http) 181 182 # --- Execute backend function --- 183 184 async def execute_function( 185 self, 186 function_name: str, 187 *params: Any, 188 ) -> Any: 189 """Execute a backend function by name. 190 191 Calls a function defined in a Squid backend service using the 192 ``@executable()`` decorator. 193 194 Args: 195 function_name: The service function name in the format 196 ``"ClassName:methodName"`` (e.g., ``"MyService:greet"``). 197 *params: Positional arguments to pass to the function. 198 Must be JSON-serializable. 199 200 Returns: 201 The function's return value, deserialized from JSON. 202 203 Raises: 204 SquidHttpError: If the function is not found or throws an error. 205 206 Example:: 207 208 result = await squid.execute_function("MyService:greet", "World") 209 # result == "Hello, World!" 210 211 data = await squid.execute_function("MyService:getData", 42, True) 212 """ 213 result = await self._http.post( 214 f"backend-function/execute?{function_name}", 215 { 216 "functionName": function_name, 217 "paramsArrayStr": json.dumps(list(params)), 218 }, 219 ) 220 if isinstance(result, dict): 221 payload = result.get("payload") 222 if isinstance(payload, str): 223 return json.loads(payload) 224 return payload 225 return result 226 227 # --- Execute webhook --- 228 229 async def execute_webhook( 230 self, 231 webhook_id: str, 232 *, 233 body: Any = None, 234 headers: dict[str, str] | None = None, 235 method: str = "POST", 236 ) -> Any: 237 """Execute a webhook. 238 239 Calls a webhook endpoint defined in a Squid backend service 240 using the ``@webhook()`` decorator. 241 242 Args: 243 webhook_id: The webhook ID as defined in the ``@webhook("id")`` decorator. 244 body: The request body to send. Must be JSON-serializable. 245 headers: Extra HTTP headers to include in the request. 246 method: The HTTP method to use (default ``"POST"``). 247 248 Returns: 249 The webhook's response body, deserialized from JSON. 250 251 Raises: 252 SquidHttpError: If the webhook is not found or returns an error. 253 254 Example:: 255 256 result = await squid.execute_webhook("my-hook", body={"key": "value"}) 257 """ 258 return await self._http.post( 259 f"webhooks/{webhook_id}", 260 body, 261 extra_headers=headers, 262 ) 263 264 def get_webhook_url(self, webhook_id: str) -> str: 265 """Get the full URL for a webhook endpoint. 266 267 Useful for providing the webhook URL to external services that 268 need to send HTTP requests to your Squid backend. 269 270 Args: 271 webhook_id: The webhook ID. 272 273 Returns: 274 The full URL string (e.g., 275 ``"https://myapp.us-east-1.aws.squid.cloud/webhooks/my-hook"``). 276 277 Example:: 278 279 url = squid.get_webhook_url("stripe-events") 280 # url == "https://myapp-dev.us-east-1.aws.squid.cloud/webhooks/stripe-events" 281 """ 282 return build_url(self._region, self._full_app_id, f"webhooks/{webhook_id}") 283 284 # --- AI Query --- 285 286 async def execute_ai_query( 287 self, 288 integration_id: str, 289 prompt: str, 290 *, 291 options: AiQueryOptions | None = None, 292 response_format: dict[str, Any] | None = None, 293 ) -> dict: 294 """Execute an AI-powered database query. 295 296 Uses AI to generate and execute database queries based on a 297 natural language prompt. 298 299 Args: 300 integration_id: The database integration ID to query against. 301 prompt: A natural language description of the data you want. 302 options: Optional :class:`AiQueryOptions` controlling collection 303 selection, query generation (including ``allowClarification``), 304 result analysis (including ``enableCodeInterpreter``), memory, 305 AI validation, per-stage model overrides via ``aiOptions``, 306 and custom instructions. 307 response_format: Optional structured output format, e.g., 308 ``{"type": "json_schema", "schema": {...}}``. 309 310 Returns: 311 An ``AiQueryResponse`` dict containing: 312 - ``answer`` (str): The AI-generated answer. 313 - ``explanation`` (str): How the answer was derived. 314 - ``executedQueries`` (list): The actual queries that were run. 315 - ``success`` (bool): Whether the query succeeded. 316 - ``usedCodeInterpreter`` (bool): Whether the code 317 interpreter was used to analyze results. 318 - ``clarificationQuestion`` (str): If the AI needs more info. 319 320 Example:: 321 322 result = await squid.execute_ai_query( 323 "my-database", 324 "How many users signed up last week?", 325 options={ 326 "selectCollectionsOptions": {"collectionsToUse": ["users"]}, 327 "analyzeResultsOptions": {"enableCodeInterpreter": True}, 328 }, 329 ) 330 print(result["answer"]) 331 """ 332 return await execute_ai_query( 333 self._http, 334 integration_id, 335 prompt, 336 options=options, 337 response_format=response_format, 338 ) 339 340 # --- Lifecycle --- 341 342 async def close(self) -> None: 343 """Close the HTTP client and release resources. 344 345 Should be called when the Squid client is no longer needed. 346 Alternatively, use the client as an async context manager. 347 """ 348 await self._http.close() 349 350 async def __aenter__(self) -> Squid: 351 """Enter async context manager.""" 352 return self 353 354 async def __aexit__(self, *args: Any) -> None: 355 """Exit async context manager and close resources.""" 356 await self.close()
Squid Cloud Python client.
The main entry point for interacting with the Squid Cloud platform. Provides access to AI agents, knowledge bases, web utilities, matchmaking, document extraction, backend functions, and webhooks.
Usage::
squid = Squid(
app_id="my-app",
api_key="sk-...",
region="us-east-1.aws",
environment_id="dev",
)
# AI agent
response = await squid.ai().agent("my-agent").ask("Hello!")
# Execute backend function
result = await squid.execute_function("MyService:greet", "World")
# Web search
results = await squid.web().ai_search("latest news")
# Cleanup
await squid.close()
Can also be used as an async context manager::
async with Squid(app_id="my-app", api_key="sk-...", region="us-east-1.aws") as squid:
result = await squid.ai().agent("my-agent").ask("Hello!")
58 def __init__( 59 self, 60 app_id: str, 61 region: str, 62 api_key: str | None = None, 63 environment_id: str | None = None, 64 squid_developer_id: str | None = None, 65 ) -> None: 66 """Initialize the Squid client. 67 68 Args: 69 app_id: The Squid application ID. 70 region: The deployment region (e.g., 'us-east-1.aws', 'local'). 71 api_key: API key for authentication. Required for most operations. 72 environment_id: Environment identifier (e.g., 'dev', 'prod'). 73 Appended to app_id as '{app_id}-{environment_id}'. 74 squid_developer_id: Developer identifier for local development. 75 Appended to app_id as '{app_id}-{environment_id}-{developer_id}'. 76 """ 77 self._app_id = app_id 78 self._region = region 79 self._environment_id = environment_id 80 self._squid_developer_id = squid_developer_id 81 82 full_app_id = app_id 83 if environment_id: 84 full_app_id = f"{app_id}-{environment_id}" 85 if squid_developer_id: 86 full_app_id = f"{full_app_id}-{squid_developer_id}" 87 88 self._full_app_id = full_app_id 89 self._http = HttpTransport( 90 app_id=full_app_id, 91 region=region, 92 api_key=api_key, 93 )
Initialize the Squid client.
Arguments:
- app_id: The Squid application ID.
- region: The deployment region (e.g., 'us-east-1.aws', 'local').
- api_key: API key for authentication. Required for most operations.
- environment_id: Environment identifier (e.g., 'dev', 'prod'). Appended to app_id as '{app_id}-{environment_id}'.
- squid_developer_id: Developer identifier for local development. Appended to app_id as '{app_id}-{environment_id}-{developer_id}'.
95 @property 96 def app_id(self) -> str: 97 """The application ID (without environment/developer suffix).""" 98 return self._app_id
The application ID (without environment/developer suffix).
105 @property 106 def client_id(self) -> str: 107 """The unique client instance ID (UUID generated per Squid instance).""" 108 return self._http.client_id
The unique client instance ID (UUID generated per Squid instance).
112 def ai(self) -> AiClient: 113 """Access AI operations. 114 115 Provides access to AI agents, knowledge bases, image generation, 116 and audio transcription/synthesis. 117 118 Returns: 119 An :class:`AiClient` instance. 120 121 Example:: 122 123 agent = squid.ai().agent("my-agent") 124 response = await agent.ask("What is the weather?") 125 126 kb = squid.ai().knowledge_base("my-kb") 127 results = await kb.search("query") 128 """ 129 return AiClient(self._http)
Access AI operations.
Provides access to AI agents, knowledge bases, image generation, and audio transcription/synthesis.
Returns:
An
AiClientinstance.
Example::
agent = squid.ai().agent("my-agent")
response = await agent.ask("What is the weather?")
kb = squid.ai().knowledge_base("my-kb")
results = await kb.search("query")
131 def web(self) -> WebClient: 132 """Access web utilities. 133 134 Provides AI-powered web search, URL content extraction, 135 and short URL management. 136 137 Returns: 138 A :class:`WebClient` instance. 139 140 Example:: 141 142 content = await squid.web().get_url_content("https://example.com") 143 results = await squid.web().ai_search("latest AI news") 144 """ 145 return WebClient(self._http)
Access web utilities.
Provides AI-powered web search, URL content extraction, and short URL management.
Returns:
A
WebClientinstance.
Example::
content = await squid.web().get_url_content("https://example.com")
results = await squid.web().ai_search("latest AI news")
147 def matchmaking(self) -> MatchmakingClient: 148 """Access AI-powered matchmaking. 149 150 Provides match maker management, entity CRUD, 151 and AI-powered entity matching. 152 153 Returns: 154 A :class:`MatchmakingClient` instance. 155 156 Example:: 157 158 mm = squid.matchmaking() 159 await mm.create_match_maker("jobs", "Job matching", categories=[...]) 160 matches = await mm.find_matches("jobs", "entity-1") 161 """ 162 return MatchmakingClient(self._http)
Access AI-powered matchmaking.
Provides match maker management, entity CRUD, and AI-powered entity matching.
Returns:
A
MatchmakingClientinstance.
Example::
mm = squid.matchmaking()
await mm.create_match_maker("jobs", "Job matching", categories=[...])
matches = await mm.find_matches("jobs", "entity-1")
164 def extraction(self) -> ExtractionClient: 165 """Access document extraction and PDF creation. 166 167 Provides PDF generation from HTML or URLs, and structured data 168 extraction from documents (PDF, DOCX, images, etc.). 169 170 Returns: 171 An :class:`ExtractionClient` instance. 172 173 Example:: 174 175 pdf = await squid.extraction().create_pdf_from_html("<h1>Hello</h1>") 176 data = await squid.extraction().extract_data_from_document_url( 177 "https://example.com/doc.pdf" 178 ) 179 """ 180 return ExtractionClient(self._http)
Access document extraction and PDF creation.
Provides PDF generation from HTML or URLs, and structured data extraction from documents (PDF, DOCX, images, etc.).
Returns:
An
ExtractionClientinstance.
Example::
pdf = await squid.extraction().create_pdf_from_html("<h1>Hello</h1>")
data = await squid.extraction().extract_data_from_document_url(
"https://example.com/doc.pdf"
)
184 async def execute_function( 185 self, 186 function_name: str, 187 *params: Any, 188 ) -> Any: 189 """Execute a backend function by name. 190 191 Calls a function defined in a Squid backend service using the 192 ``@executable()`` decorator. 193 194 Args: 195 function_name: The service function name in the format 196 ``"ClassName:methodName"`` (e.g., ``"MyService:greet"``). 197 *params: Positional arguments to pass to the function. 198 Must be JSON-serializable. 199 200 Returns: 201 The function's return value, deserialized from JSON. 202 203 Raises: 204 SquidHttpError: If the function is not found or throws an error. 205 206 Example:: 207 208 result = await squid.execute_function("MyService:greet", "World") 209 # result == "Hello, World!" 210 211 data = await squid.execute_function("MyService:getData", 42, True) 212 """ 213 result = await self._http.post( 214 f"backend-function/execute?{function_name}", 215 { 216 "functionName": function_name, 217 "paramsArrayStr": json.dumps(list(params)), 218 }, 219 ) 220 if isinstance(result, dict): 221 payload = result.get("payload") 222 if isinstance(payload, str): 223 return json.loads(payload) 224 return payload 225 return result
Execute a backend function by name.
Calls a function defined in a Squid backend service using the
@executable() decorator.
Arguments:
- function_name: The service function name in the format
"ClassName:methodName"(e.g.,"MyService:greet"). - *params: Positional arguments to pass to the function. Must be JSON-serializable.
Returns:
The function's return value, deserialized from JSON.
Raises:
- SquidHttpError: If the function is not found or throws an error.
Example::
result = await squid.execute_function("MyService:greet", "World")
# result == "Hello, World!"
data = await squid.execute_function("MyService:getData", 42, True)
229 async def execute_webhook( 230 self, 231 webhook_id: str, 232 *, 233 body: Any = None, 234 headers: dict[str, str] | None = None, 235 method: str = "POST", 236 ) -> Any: 237 """Execute a webhook. 238 239 Calls a webhook endpoint defined in a Squid backend service 240 using the ``@webhook()`` decorator. 241 242 Args: 243 webhook_id: The webhook ID as defined in the ``@webhook("id")`` decorator. 244 body: The request body to send. Must be JSON-serializable. 245 headers: Extra HTTP headers to include in the request. 246 method: The HTTP method to use (default ``"POST"``). 247 248 Returns: 249 The webhook's response body, deserialized from JSON. 250 251 Raises: 252 SquidHttpError: If the webhook is not found or returns an error. 253 254 Example:: 255 256 result = await squid.execute_webhook("my-hook", body={"key": "value"}) 257 """ 258 return await self._http.post( 259 f"webhooks/{webhook_id}", 260 body, 261 extra_headers=headers, 262 )
Execute a webhook.
Calls a webhook endpoint defined in a Squid backend service
using the @webhook() decorator.
Arguments:
- webhook_id: The webhook ID as defined in the
@webhook("id")decorator. - body: The request body to send. Must be JSON-serializable.
- headers: Extra HTTP headers to include in the request.
- method: The HTTP method to use (default
"POST").
Returns:
The webhook's response body, deserialized from JSON.
Raises:
- SquidHttpError: If the webhook is not found or returns an error.
Example::
result = await squid.execute_webhook("my-hook", body={"key": "value"})
264 def get_webhook_url(self, webhook_id: str) -> str: 265 """Get the full URL for a webhook endpoint. 266 267 Useful for providing the webhook URL to external services that 268 need to send HTTP requests to your Squid backend. 269 270 Args: 271 webhook_id: The webhook ID. 272 273 Returns: 274 The full URL string (e.g., 275 ``"https://myapp.us-east-1.aws.squid.cloud/webhooks/my-hook"``). 276 277 Example:: 278 279 url = squid.get_webhook_url("stripe-events") 280 # url == "https://myapp-dev.us-east-1.aws.squid.cloud/webhooks/stripe-events" 281 """ 282 return build_url(self._region, self._full_app_id, f"webhooks/{webhook_id}")
Get the full URL for a webhook endpoint.
Useful for providing the webhook URL to external services that need to send HTTP requests to your Squid backend.
Arguments:
- webhook_id: The webhook ID.
Returns:
The full URL string (e.g.,
"https://myapp.us-east-1.aws.squid.cloud/webhooks/my-hook").
Example::
url = squid.get_webhook_url("stripe-events")
# url == "https://myapp-dev.us-east-1.aws.squid.cloud/webhooks/stripe-events"
286 async def execute_ai_query( 287 self, 288 integration_id: str, 289 prompt: str, 290 *, 291 options: AiQueryOptions | None = None, 292 response_format: dict[str, Any] | None = None, 293 ) -> dict: 294 """Execute an AI-powered database query. 295 296 Uses AI to generate and execute database queries based on a 297 natural language prompt. 298 299 Args: 300 integration_id: The database integration ID to query against. 301 prompt: A natural language description of the data you want. 302 options: Optional :class:`AiQueryOptions` controlling collection 303 selection, query generation (including ``allowClarification``), 304 result analysis (including ``enableCodeInterpreter``), memory, 305 AI validation, per-stage model overrides via ``aiOptions``, 306 and custom instructions. 307 response_format: Optional structured output format, e.g., 308 ``{"type": "json_schema", "schema": {...}}``. 309 310 Returns: 311 An ``AiQueryResponse`` dict containing: 312 - ``answer`` (str): The AI-generated answer. 313 - ``explanation`` (str): How the answer was derived. 314 - ``executedQueries`` (list): The actual queries that were run. 315 - ``success`` (bool): Whether the query succeeded. 316 - ``usedCodeInterpreter`` (bool): Whether the code 317 interpreter was used to analyze results. 318 - ``clarificationQuestion`` (str): If the AI needs more info. 319 320 Example:: 321 322 result = await squid.execute_ai_query( 323 "my-database", 324 "How many users signed up last week?", 325 options={ 326 "selectCollectionsOptions": {"collectionsToUse": ["users"]}, 327 "analyzeResultsOptions": {"enableCodeInterpreter": True}, 328 }, 329 ) 330 print(result["answer"]) 331 """ 332 return await execute_ai_query( 333 self._http, 334 integration_id, 335 prompt, 336 options=options, 337 response_format=response_format, 338 )
Execute an AI-powered database query.
Uses AI to generate and execute database queries based on a natural language prompt.
Arguments:
- integration_id: The database integration ID to query against.
- prompt: A natural language description of the data you want.
- options: Optional
AiQueryOptionscontrolling collection selection, query generation (includingallowClarification), result analysis (includingenableCodeInterpreter), memory, AI validation, per-stage model overrides viaaiOptions, and custom instructions. - response_format: Optional structured output format, e.g.,
{"type": "json_schema", "schema": {...}}.
Returns:
An
AiQueryResponsedict containing: -answer(str): The AI-generated answer. -explanation(str): How the answer was derived. -executedQueries(list): The actual queries that were run. -success(bool): Whether the query succeeded. -usedCodeInterpreter(bool): Whether the code interpreter was used to analyze results. -clarificationQuestion(str): If the AI needs more info.
Example::
result = await squid.execute_ai_query(
"my-database",
"How many users signed up last week?",
options={
"selectCollectionsOptions": {"collectionsToUse": ["users"]},
"analyzeResultsOptions": {"enableCodeInterpreter": True},
},
)
print(result["answer"])
342 async def close(self) -> None: 343 """Close the HTTP client and release resources. 344 345 Should be called when the Squid client is no longer needed. 346 Alternatively, use the client as an async context manager. 347 """ 348 await self._http.close()
Close the HTTP client and release resources.
Should be called when the Squid client is no longer needed. Alternatively, use the client as an async context manager.
83class SquidHttpError(Exception): 84 """Raised when the Squid API returns an HTTP error response (status >= 400). 85 86 Attributes: 87 status_code: The HTTP status code. 88 url: The URL that was requested. 89 body: The parsed response body, if available. 90 """ 91 92 def __init__(self, status_code: int, message: str, url: str, body: Any = None): 93 self.status_code = status_code 94 self.url = url 95 self.body = body 96 super().__init__(f"HTTP {status_code}: {message} (url={url})")
Raised when the Squid API returns an HTTP error response (status >= 400).
Attributes:
- status_code: The HTTP status code.
- url: The URL that was requested.
- body: The parsed response body, if available.
756class StableDiffusionOptions(TypedDict, total=False): 757 """Options for Stable Diffusion Core image generation.""" 758 759 modelName: Literal["stable-diffusion-core"] 760 aspectRatio: Literal["16:9", "1:1", "21:9", "2:3", "3:2", "4:5", "5:4", "9:16", "9:21"] 761 negativePrompt: str 762 seed: int 763 stylePreset: str 764 outputFormat: str
Options for Stable Diffusion Core image generation.
563class TextContextRequest(TypedDict, total=False): 564 """Request to upsert a text context.""" 565 566 contextId: str 567 type: Literal["text"] 568 title: str 569 text: str 570 metadata: dict[str, Any] 571 options: AiContextTextOptions
Request to upsert a text context.
376class UpsertAgentOptions(TypedDict, total=False): 377 """Options for creating/updating an agent.""" 378 379 description: str 380 """Description of the agent's purpose.""" 381 isPublic: bool 382 """Whether the agent is publicly accessible.""" 383 auditLog: bool 384 """Enable audit logging.""" 385 auditLogFullContext: bool 386 """Record the full agent context (system instructions and retrieved knowledge-base content) in the audit log.""" 387 apiKey: str 388 """API key for this agent.""" 389 mcpServer: AiAgentMcpServerConfig 390 """Optional configuration for exposing the agent as an MCP server.""" 391 options: AiChatOptions 392 """Default chat options."""
Options for creating/updating an agent.
874class WebAiSearchResponse(TypedDict): 875 """Response from AI web search.""" 876 877 markdownText: str 878 citedUrls: list[dict[str, str]]
Response from AI web search.
16class WebClient: 17 """Web utilities: AI search, URL content, short URLs.""" 18 19 def __init__(self, http: HttpTransport) -> None: 20 self._http = http 21 22 async def ai_search( 23 self, query: str, allowed_domains: list[str] | None = None 24 ) -> WebAiSearchResponse: 25 """Perform an AI-powered web search. 26 27 When allowed_domains is provided, the search is restricted to those domains 28 (subdomains included) and every cited URL belongs to one of them. 29 30 Returns WebAiSearchResponse with 'markdownText' and 'citedUrls'. 31 """ 32 body: dict[str, object] = {"query": query} 33 if allowed_domains is not None: 34 body["allowedDomains"] = allowed_domains 35 return await self._http.post("squid-api/v1/web/aiSearch", body) 36 37 async def get_url_content(self, url: str) -> str: 38 """Fetch and extract content from a URL as markdown.""" 39 result = await self._http.post("squid-api/v1/web/getUrlContent", {"url": url}) 40 if isinstance(result, dict): 41 return result.get("markdownText", "") 42 return str(result) if result else "" 43 44 async def create_short_url( 45 self, 46 url: str, 47 *, 48 seconds_to_live: int | None = None, 49 file_extension: str | None = None, 50 ) -> WebShortUrlResponse: 51 """Create a short URL. 52 53 Returns WebShortUrlResponse with 'id', 'shortUrl', 'expiry'. 54 """ 55 body: dict = {"url": url} 56 if seconds_to_live is not None: 57 body["secondsToLive"] = seconds_to_live 58 if file_extension is not None: 59 body["fileExtension"] = file_extension 60 return await self._http.post("squid-api/v1/web/createShortUrl", body) 61 62 async def create_short_urls( 63 self, 64 urls: list[str], 65 *, 66 seconds_to_live: int | None = None, 67 file_extension: str | None = None, 68 ) -> WebShortUrlBulkResponse: 69 """Create multiple short URLs in bulk. 70 71 Returns WebShortUrlBulkResponse with 'ids', 'shortUrls', 'expiry'. 72 """ 73 body: dict = {"urls": urls} 74 if seconds_to_live is not None: 75 body["secondsToLive"] = seconds_to_live 76 if file_extension is not None: 77 body["fileExtension"] = file_extension 78 return await self._http.post("squid-api/v1/web/createShortUrls", body) 79 80 async def delete_short_url(self, url_id: str) -> None: 81 """Delete a short URL.""" 82 await self._http.post("squid-api/v1/web/deleteShortUrl", {"id": url_id}) 83 84 async def delete_short_urls(self, url_ids: list[str]) -> None: 85 """Delete multiple short URLs.""" 86 await self._http.post("squid-api/v1/web/deleteShortUrls", {"ids": url_ids})
Web utilities: AI search, URL content, short URLs.
22 async def ai_search( 23 self, query: str, allowed_domains: list[str] | None = None 24 ) -> WebAiSearchResponse: 25 """Perform an AI-powered web search. 26 27 When allowed_domains is provided, the search is restricted to those domains 28 (subdomains included) and every cited URL belongs to one of them. 29 30 Returns WebAiSearchResponse with 'markdownText' and 'citedUrls'. 31 """ 32 body: dict[str, object] = {"query": query} 33 if allowed_domains is not None: 34 body["allowedDomains"] = allowed_domains 35 return await self._http.post("squid-api/v1/web/aiSearch", body)
Perform an AI-powered web search.
When allowed_domains is provided, the search is restricted to those domains (subdomains included) and every cited URL belongs to one of them.
Returns WebAiSearchResponse with 'markdownText' and 'citedUrls'.
37 async def get_url_content(self, url: str) -> str: 38 """Fetch and extract content from a URL as markdown.""" 39 result = await self._http.post("squid-api/v1/web/getUrlContent", {"url": url}) 40 if isinstance(result, dict): 41 return result.get("markdownText", "") 42 return str(result) if result else ""
Fetch and extract content from a URL as markdown.
44 async def create_short_url( 45 self, 46 url: str, 47 *, 48 seconds_to_live: int | None = None, 49 file_extension: str | None = None, 50 ) -> WebShortUrlResponse: 51 """Create a short URL. 52 53 Returns WebShortUrlResponse with 'id', 'shortUrl', 'expiry'. 54 """ 55 body: dict = {"url": url} 56 if seconds_to_live is not None: 57 body["secondsToLive"] = seconds_to_live 58 if file_extension is not None: 59 body["fileExtension"] = file_extension 60 return await self._http.post("squid-api/v1/web/createShortUrl", body)
Create a short URL.
Returns WebShortUrlResponse with 'id', 'shortUrl', 'expiry'.
62 async def create_short_urls( 63 self, 64 urls: list[str], 65 *, 66 seconds_to_live: int | None = None, 67 file_extension: str | None = None, 68 ) -> WebShortUrlBulkResponse: 69 """Create multiple short URLs in bulk. 70 71 Returns WebShortUrlBulkResponse with 'ids', 'shortUrls', 'expiry'. 72 """ 73 body: dict = {"urls": urls} 74 if seconds_to_live is not None: 75 body["secondsToLive"] = seconds_to_live 76 if file_extension is not None: 77 body["fileExtension"] = file_extension 78 return await self._http.post("squid-api/v1/web/createShortUrls", body)
Create multiple short URLs in bulk.
Returns WebShortUrlBulkResponse with 'ids', 'shortUrls', 'expiry'.
866class WebShortUrlBulkResponse(TypedDict): 867 """Response from creating bulk short URLs.""" 868 869 ids: list[str] 870 shortUrls: list[str] 871 expiry: str
Response from creating bulk short URLs.
858class WebShortUrlResponse(TypedDict): 859 """Response from creating a short URL.""" 860 861 id: str 862 shortUrl: str 863 expiry: str
Response from creating a short URL.