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    AiAgentMemoryOptions,
 39    AiAgentResponseFormat,
 40    AiAudioCreateSpeechOptions,
 41    AiChatModelSelection,
 42    AiChatOptions,
 43    AiChatPromptQuotas,
 44    AiConnectedAgentMetadata,
 45    AiConnectedIntegrationMetadata,
 46    AiConnectedKnowledgeBaseMetadata,
 47    AiContextFileOptions,
 48    AiContextTextOptions,
 49    AiEmbeddingsModelSelection,
 50    AiFileUrl,
 51    AiFunctionAttributes,
 52    AiFunctionMetadata,
 53    AiFunctionParam,
 54    AiKnowledgeBase,
 55    AiKnowledgeBaseMetadataField,
 56    AiQueryAnalyzeResultsOptions,
 57    AiQueryCollectionsSelectionRunMode,
 58    AiQueryGenerateQueryOptions,
 59    AiQueryOptions,
 60    AiQuerySelectCollectionsOptions,
 61    AiQueryValidateWithAiOptions,
 62    AiSessionContext,
 63    AiStructuredOutputFormat,
 64    ContextRequest,
 65    CreatePdfDimensionsOptions,
 66    CreatePdfFormatOptions,
 67    CreatePdfOutputOptions,
 68    ExtractDataFromDocumentOptions,
 69    FileContextRequest,
 70    FluxOptions,
 71    GptImageOptions,
 72    GuardrailsOptions,
 73    ImageGenerateOptions,
 74    IntegrationEmbeddingModelSpec,
 75    IntegrationModelSpec,
 76    KnowledgeBaseSearchOptions,
 77    MmCategory,
 78    MmEntity,
 79    MmFindMatchesOptions,
 80    MmListEntitiesOptions,
 81    ModelIdSpec,
 82    StableDiffusionOptions,
 83    TextContextRequest,
 84    UpsertAgentOptions,
 85    WebAiSearchResponse,
 86    WebShortUrlBulkResponse,
 87    WebShortUrlResponse,
 88)
 89from squidcloud.web import WebClient
 90
 91__all__ = [
 92    "AgentClient",
 93    "AiAgent",
 94    "AiAgentExecutionPlanOptions",
 95    "AiAgentMemoryOptions",
 96    "AiAgentResponseFormat",
 97    "AiAudioCreateSpeechOptions",
 98    "AiChatModelSelection",
 99    # AI Chat
100    "AiChatOptions",
101    "AiChatPromptQuotas",
102    "AiClient",
103    "AiConnectedAgentMetadata",
104    "AiConnectedIntegrationMetadata",
105    "AiConnectedKnowledgeBaseMetadata",
106    "AiContextFileOptions",
107    "AiContextTextOptions",
108    "AiEmbeddingsModelSelection",
109    "AiFileUrl",
110    "AiFunctionAttributes",
111    "AiFunctionMetadata",
112    "AiFunctionParam",
113    # Knowledge Base
114    "AiKnowledgeBase",
115    "AiKnowledgeBaseMetadataField",
116    # AI Query
117    "AiQueryAnalyzeResultsOptions",
118    "AiQueryCollectionsSelectionRunMode",
119    "AiQueryGenerateQueryOptions",
120    "AiQueryOptions",
121    "AiQuerySelectCollectionsOptions",
122    "AiQueryValidateWithAiOptions",
123    "AiSessionContext",
124    "AiStructuredOutputFormat",
125    "AudioClient",
126    "ContextRequest",
127    "CreatePdfDimensionsOptions",
128    "CreatePdfFormatOptions",
129    # Extraction
130    "CreatePdfOutputOptions",
131    "ExtractDataFromDocumentOptions",
132    "ExtractionClient",
133    "FileContextRequest",
134    "FluxOptions",
135    "GptImageOptions",
136    "GuardrailsOptions",
137    # Image
138    "ImageClient",
139    "ImageGenerateOptions",
140    "IntegrationEmbeddingModelSpec",
141    "IntegrationModelSpec",
142    "KnowledgeBaseClient",
143    "KnowledgeBaseSearchOptions",
144    # Matchmaking
145    "MatchmakingClient",
146    "MmCategory",
147    "MmEntity",
148    "MmFindMatchesOptions",
149    "MmListEntitiesOptions",
150    "ModelIdSpec",
151    "Squid",
152    "SquidHttpError",
153    "StableDiffusionOptions",
154    "TextContextRequest",
155    "UpsertAgentOptions",
156    # Web
157    "WebAiSearchResponse",
158    "WebClient",
159    "WebShortUrlBulkResponse",
160    "WebShortUrlResponse",
161]
class AgentClient:
141class AgentClient:
142    """Operations on a single AI agent.
143
144    Provides methods for chatting with an agent, managing its configuration,
145    updating guardrails, and working with revisions.
146
147    Obtained via :meth:`AiClient.agent`.
148
149    Example::
150
151        agent = squid.ai().agent("my-agent")
152        response = await agent.ask("What is the weather?", options={"temperature": 0.7})
153        await agent.update_instructions("Always respond in haiku format.")
154    """
155
156    def __init__(self, http: HttpTransport, agent_id: str) -> None:
157        self._http = http
158        self._agent_id = agent_id
159
160    # --- Chat ---
161
162    async def ask(
163        self,
164        prompt: str,
165        options: AiChatOptions | None = None,
166    ) -> str:
167        """Ask the agent a question and get a text response.
168
169        Args:
170            prompt: The user's question or instruction.
171            options: Chat options controlling model, temperature, memory,
172                functions, guardrails, and more. See :class:`AiChatOptions`.
173
174        Returns:
175            The agent's response as a string.
176
177        Raises:
178            SquidHttpError: If the agent is not found or the request fails.
179
180        Example::
181
182            response = await agent.ask(
183                "Summarize this document",
184                options={
185                    "model": "gemini-3-flash",
186                    "temperature": 0.3,
187                    "memoryOptions": {"memoryId": "session-1", "memoryMode": "read-write"},
188                },
189            )
190        """
191        result = await self._http.post(
192            "squid-api/v1/ai/agent/ask",
193            {"agentId": self._agent_id, "prompt": prompt, "options": options or {}},
194        )
195        return result.get("responseString", "") if result else ""
196
197    async def ask_with_annotations(
198        self,
199        prompt: str,
200        options: AiChatOptions | None = None,
201    ) -> dict:
202        """Ask the agent and get a response with annotations.
203
204        Annotations include file references, citations, and other metadata
205        the agent may attach to its response.
206
207        Args:
208            prompt: The user's question or instruction.
209            options: Chat options. See :class:`AiChatOptions`.
210
211        Returns:
212            A dict with:
213                - ``responseString`` (str): The text response.
214                - ``annotations`` (dict): Annotation metadata keyed by ID.
215
216        Example::
217
218            result = await agent.ask_with_annotations("Find relevant docs")
219            print(result["responseString"])
220            for ann_id, ann in result.get("annotations", {}).items():
221                print(f"  Annotation: {ann}")
222        """
223        return await self._http.post(
224            "squid-api/v1/ai/agent/askWithAnnotations",
225            {"agentId": self._agent_id, "prompt": prompt, "options": options or {}},
226        )
227
228    # --- Management ---
229
230    async def get(self) -> dict | None:
231        """Get the agent's configuration.
232
233        Returns:
234            An ``AiAgent`` dict with keys: ``id``, ``createdAt``, ``updatedAt``,
235            ``description``, ``isPublic``, ``auditLog``, ``options``, ``apiKey``.
236            Returns ``None`` if the agent does not exist.
237        """
238        return await self._http.get(f"squid-api/v1/ai/agent/get/{self._agent_id}")
239
240    async def upsert(
241        self,
242        *,
243        description: str | None = None,
244        is_public: bool | None = None,
245        audit_log: bool | None = None,
246        api_key: str | None = None,
247        options: AiChatOptions | None = None,
248    ) -> None:
249        """Create or update the agent.
250
251        If the agent does not exist, it is created. If it exists, the provided
252        fields are updated (fields set to ``None`` are left unchanged).
253
254        Args:
255            description: A description of the agent's purpose or capabilities.
256            is_public: Whether the agent is publicly accessible (default ``False``).
257            audit_log: Enable audit logging for the agent's activities.
258            api_key: Optional API key used specifically for this agent.
259            options: Default chat options applied to every request unless
260                overridden per-call. See :class:`AiChatOptions`.
261
262        Example::
263
264            await agent.upsert(
265                description="Customer support agent",
266                options={"model": "gemini-3-flash", "temperature": 0.5},
267            )
268        """
269        body: dict[str, Any] = {"id": self._agent_id}
270        if description is not None:
271            body["description"] = description
272        if is_public is not None:
273            body["isPublic"] = is_public
274        if audit_log is not None:
275            body["auditLog"] = audit_log
276        if api_key is not None:
277            body["apiKey"] = api_key
278        if options is not None:
279            body["options"] = options
280        await self._http.post("squid-api/v1/ai/agent/upsert", body)
281
282    async def delete(self) -> None:
283        """Delete the agent permanently."""
284        await self._http.post("squid-api/v1/ai/agent/delete", {"agentId": self._agent_id})
285
286    async def update_instructions(self, instructions: str) -> None:
287        """Update the agent's system instructions.
288
289        Args:
290            instructions: The new system prompt / instructions text.
291        """
292        await self._http.post(
293            "squid-api/v1/ai/agent/updateInstructions",
294            {"agentId": self._agent_id, "instructions": instructions},
295        )
296
297    async def update_model(self, model: AiChatModelSelection) -> None:
298        """Update the agent's default LLM model.
299
300        Args:
301            model: A model name string (e.g., ``'gemini-3-flash'``) or an
302                ``IntegrationModelSpec`` dict (``{'integrationId': str, 'model': str}``).
303        """
304        await self._http.post(
305            "squid-api/v1/ai/agent/updateModel",
306            {"agentId": self._agent_id, "model": model},
307        )
308
309    async def update_connected_agents(
310        self, connected_agents: list[AiConnectedAgentMetadata]
311    ) -> None:
312        """Update the list of connected agents.
313
314        Connected agents can be called by this agent during conversations.
315
316        Args:
317            connected_agents: List of ``{'agentId': str, 'description': str}`` dicts.
318        """
319        await self._http.post(
320            "squid-api/v1/ai/agent/updateConnectedAgents",
321            {"agentId": self._agent_id, "connectedAgents": connected_agents},
322        )
323
324    async def update_guardrails(self, guardrails: GuardrailsOptions) -> None:
325        """Update the agent's guardrail settings.
326
327        Args:
328            guardrails: A :class:`GuardrailsOptions` dict with optional keys:
329                ``custom``, ``disablePii``, ``professionalTone``,
330                ``offTopicAnswers``, ``disableProfanity``.
331
332        Example::
333
334            await agent.update_guardrails(
335                {
336                    "professionalTone": True,
337                    "disableProfanity": True,
338                }
339            )
340        """
341        await self._http.post(
342            "squid-api/v1/ai/agent/updateGuardrails",
343            {"agentId": self._agent_id, "guardrails": guardrails},
344        )
345
346    async def update_custom_guardrails(self, custom_guardrail: str) -> None:
347        """Update the custom guardrail instruction text.
348
349        Args:
350            custom_guardrail: Free-form guardrail instruction string.
351        """
352        await self._http.post(
353            "squid-api/v1/ai/agent/updateCustomGuardrails",
354            {"agentId": self._agent_id, "customGuardrail": custom_guardrail},
355        )
356
357    async def delete_custom_guardrails(self) -> None:
358        """Delete the custom guardrail, reverting to defaults."""
359        await self._http.post(
360            "squid-api/v1/ai/agent/deleteCustomGuardrails",
361            {"agentId": self._agent_id},
362        )
363
364    # --- Revisions ---
365
366    async def list_revisions(self) -> list[dict]:
367        """List all revisions of this agent.
368
369        Returns:
370            A list of ``AiAgentRevision`` dicts, each containing:
371            ``agentId``, ``revisionNumber``, ``action``, ``createdAt``,
372            ``agentSnapshot``.
373        """
374        result = await self._http.get(f"squid-api/v1/ai/agent/revisions/{self._agent_id}")
375        return result.get("revisions", []) if result else []
376
377    async def restore_revision(self, revision_number: int) -> None:
378        """Restore the agent to a previous revision.
379
380        Args:
381            revision_number: The revision number to restore.
382        """
383        await self._http.post(
384            "squid-api/v1/ai/agent/restoreRevision",
385            {"agentId": self._agent_id, "revisionNumber": revision_number},
386        )
387
388    async def delete_revision(self, revision_number: int) -> None:
389        """Delete a specific revision.
390
391        Args:
392            revision_number: The revision number to delete.
393        """
394        await self._http.post(
395            "squid-api/v1/ai/agent/deleteRevision",
396            {"agentId": self._agent_id, "revisionNumber": revision_number},
397        )

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.")
AgentClient(http: squidcloud.http.HttpTransport, agent_id: str)
156    def __init__(self, http: HttpTransport, agent_id: str) -> None:
157        self._http = http
158        self._agent_id = agent_id
async def ask( self, prompt: str, options: AiChatOptions | None = None) -> str:
162    async def ask(
163        self,
164        prompt: str,
165        options: AiChatOptions | None = None,
166    ) -> str:
167        """Ask the agent a question and get a text response.
168
169        Args:
170            prompt: The user's question or instruction.
171            options: Chat options controlling model, temperature, memory,
172                functions, guardrails, and more. See :class:`AiChatOptions`.
173
174        Returns:
175            The agent's response as a string.
176
177        Raises:
178            SquidHttpError: If the agent is not found or the request fails.
179
180        Example::
181
182            response = await agent.ask(
183                "Summarize this document",
184                options={
185                    "model": "gemini-3-flash",
186                    "temperature": 0.3,
187                    "memoryOptions": {"memoryId": "session-1", "memoryMode": "read-write"},
188                },
189            )
190        """
191        result = await self._http.post(
192            "squid-api/v1/ai/agent/ask",
193            {"agentId": self._agent_id, "prompt": prompt, "options": options or {}},
194        )
195        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"},
    },
)
async def ask_with_annotations( self, prompt: str, options: AiChatOptions | None = None) -> dict:
197    async def ask_with_annotations(
198        self,
199        prompt: str,
200        options: AiChatOptions | None = None,
201    ) -> dict:
202        """Ask the agent and get a response with annotations.
203
204        Annotations include file references, citations, and other metadata
205        the agent may attach to its response.
206
207        Args:
208            prompt: The user's question or instruction.
209            options: Chat options. See :class:`AiChatOptions`.
210
211        Returns:
212            A dict with:
213                - ``responseString`` (str): The text response.
214                - ``annotations`` (dict): Annotation metadata keyed by ID.
215
216        Example::
217
218            result = await agent.ask_with_annotations("Find relevant docs")
219            print(result["responseString"])
220            for ann_id, ann in result.get("annotations", {}).items():
221                print(f"  Annotation: {ann}")
222        """
223        return await self._http.post(
224            "squid-api/v1/ai/agent/askWithAnnotations",
225            {"agentId": self._agent_id, "prompt": prompt, "options": options or {}},
226        )

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}")
async def get(self) -> dict | None:
230    async def get(self) -> dict | None:
231        """Get the agent's configuration.
232
233        Returns:
234            An ``AiAgent`` dict with keys: ``id``, ``createdAt``, ``updatedAt``,
235            ``description``, ``isPublic``, ``auditLog``, ``options``, ``apiKey``.
236            Returns ``None`` if the agent does not exist.
237        """
238        return await self._http.get(f"squid-api/v1/ai/agent/get/{self._agent_id}")

Get the agent's configuration.

Returns:

An AiAgent dict with keys: id, createdAt, updatedAt, description, isPublic, auditLog, options, apiKey. Returns None if the agent does not exist.

async def upsert( self, *, description: str | None = None, is_public: bool | None = None, audit_log: bool | None = None, api_key: str | None = None, options: AiChatOptions | None = None) -> None:
240    async def upsert(
241        self,
242        *,
243        description: str | None = None,
244        is_public: bool | None = None,
245        audit_log: bool | None = None,
246        api_key: str | None = None,
247        options: AiChatOptions | None = None,
248    ) -> None:
249        """Create or update the agent.
250
251        If the agent does not exist, it is created. If it exists, the provided
252        fields are updated (fields set to ``None`` are left unchanged).
253
254        Args:
255            description: A description of the agent's purpose or capabilities.
256            is_public: Whether the agent is publicly accessible (default ``False``).
257            audit_log: Enable audit logging for the agent's activities.
258            api_key: Optional API key used specifically for this agent.
259            options: Default chat options applied to every request unless
260                overridden per-call. See :class:`AiChatOptions`.
261
262        Example::
263
264            await agent.upsert(
265                description="Customer support agent",
266                options={"model": "gemini-3-flash", "temperature": 0.5},
267            )
268        """
269        body: dict[str, Any] = {"id": self._agent_id}
270        if description is not None:
271            body["description"] = description
272        if is_public is not None:
273            body["isPublic"] = is_public
274        if audit_log is not None:
275            body["auditLog"] = audit_log
276        if api_key is not None:
277            body["apiKey"] = api_key
278        if options is not None:
279            body["options"] = options
280        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.
  • api_key: Optional API key used specifically for this agent.
  • 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},
)
async def delete(self) -> None:
282    async def delete(self) -> None:
283        """Delete the agent permanently."""
284        await self._http.post("squid-api/v1/ai/agent/delete", {"agentId": self._agent_id})

Delete the agent permanently.

async def update_instructions(self, instructions: str) -> None:
286    async def update_instructions(self, instructions: str) -> None:
287        """Update the agent's system instructions.
288
289        Args:
290            instructions: The new system prompt / instructions text.
291        """
292        await self._http.post(
293            "squid-api/v1/ai/agent/updateInstructions",
294            {"agentId": self._agent_id, "instructions": instructions},
295        )

Update the agent's system instructions.

Arguments:
  • instructions: The new system prompt / instructions text.
async def update_model(self, model: str | IntegrationModelSpec) -> None:
297    async def update_model(self, model: AiChatModelSelection) -> None:
298        """Update the agent's default LLM model.
299
300        Args:
301            model: A model name string (e.g., ``'gemini-3-flash'``) or an
302                ``IntegrationModelSpec`` dict (``{'integrationId': str, 'model': str}``).
303        """
304        await self._http.post(
305            "squid-api/v1/ai/agent/updateModel",
306            {"agentId": self._agent_id, "model": model},
307        )

Update the agent's default LLM model.

Arguments:
  • model: A model name string (e.g., 'gemini-3-flash') or an IntegrationModelSpec dict ({'integrationId': str, 'model': str}).
async def update_connected_agents( self, connected_agents: list[AiConnectedAgentMetadata]) -> None:
309    async def update_connected_agents(
310        self, connected_agents: list[AiConnectedAgentMetadata]
311    ) -> None:
312        """Update the list of connected agents.
313
314        Connected agents can be called by this agent during conversations.
315
316        Args:
317            connected_agents: List of ``{'agentId': str, 'description': str}`` dicts.
318        """
319        await self._http.post(
320            "squid-api/v1/ai/agent/updateConnectedAgents",
321            {"agentId": self._agent_id, "connectedAgents": connected_agents},
322        )

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.
async def update_guardrails(self, guardrails: GuardrailsOptions) -> None:
324    async def update_guardrails(self, guardrails: GuardrailsOptions) -> None:
325        """Update the agent's guardrail settings.
326
327        Args:
328            guardrails: A :class:`GuardrailsOptions` dict with optional keys:
329                ``custom``, ``disablePii``, ``professionalTone``,
330                ``offTopicAnswers``, ``disableProfanity``.
331
332        Example::
333
334            await agent.update_guardrails(
335                {
336                    "professionalTone": True,
337                    "disableProfanity": True,
338                }
339            )
340        """
341        await self._http.post(
342            "squid-api/v1/ai/agent/updateGuardrails",
343            {"agentId": self._agent_id, "guardrails": guardrails},
344        )

Update the agent's guardrail settings.

Arguments:
  • guardrails: A GuardrailsOptions dict with optional keys: custom, disablePii, professionalTone, offTopicAnswers, disableProfanity.

Example::

await agent.update_guardrails(
    {
        "professionalTone": True,
        "disableProfanity": True,
    }
)
async def update_custom_guardrails(self, custom_guardrail: str) -> None:
346    async def update_custom_guardrails(self, custom_guardrail: str) -> None:
347        """Update the custom guardrail instruction text.
348
349        Args:
350            custom_guardrail: Free-form guardrail instruction string.
351        """
352        await self._http.post(
353            "squid-api/v1/ai/agent/updateCustomGuardrails",
354            {"agentId": self._agent_id, "customGuardrail": custom_guardrail},
355        )

Update the custom guardrail instruction text.

Arguments:
  • custom_guardrail: Free-form guardrail instruction string.
async def delete_custom_guardrails(self) -> None:
357    async def delete_custom_guardrails(self) -> None:
358        """Delete the custom guardrail, reverting to defaults."""
359        await self._http.post(
360            "squid-api/v1/ai/agent/deleteCustomGuardrails",
361            {"agentId": self._agent_id},
362        )

Delete the custom guardrail, reverting to defaults.

async def list_revisions(self) -> list[dict]:
366    async def list_revisions(self) -> list[dict]:
367        """List all revisions of this agent.
368
369        Returns:
370            A list of ``AiAgentRevision`` dicts, each containing:
371            ``agentId``, ``revisionNumber``, ``action``, ``createdAt``,
372            ``agentSnapshot``.
373        """
374        result = await self._http.get(f"squid-api/v1/ai/agent/revisions/{self._agent_id}")
375        return result.get("revisions", []) if result else []

List all revisions of this agent.

Returns:

A list of AiAgentRevision dicts, each containing: agentId, revisionNumber, action, createdAt, agentSnapshot.

async def restore_revision(self, revision_number: int) -> None:
377    async def restore_revision(self, revision_number: int) -> None:
378        """Restore the agent to a previous revision.
379
380        Args:
381            revision_number: The revision number to restore.
382        """
383        await self._http.post(
384            "squid-api/v1/ai/agent/restoreRevision",
385            {"agentId": self._agent_id, "revisionNumber": revision_number},
386        )

Restore the agent to a previous revision.

Arguments:
  • revision_number: The revision number to restore.
async def delete_revision(self, revision_number: int) -> None:
388    async def delete_revision(self, revision_number: int) -> None:
389        """Delete a specific revision.
390
391        Args:
392            revision_number: The revision number to delete.
393        """
394        await self._http.post(
395            "squid-api/v1/ai/agent/deleteRevision",
396            {"agentId": self._agent_id, "revisionNumber": revision_number},
397        )

Delete a specific revision.

Arguments:
  • revision_number: The revision number to delete.
class AiAgent(typing.TypedDict):
354class AiAgent(TypedDict, total=False):
355    """A definition of an AI agent with its properties and default chat options.
356
357    Returned by :meth:`AiClient.list_agents`.
358    """
359
360    id: str
361    """The unique identifier of the AI agent. Required."""
362    createdAt: str
363    """ISO 8601 timestamp of when the agent was created. Required."""
364    updatedAt: str
365    """ISO 8601 timestamp of when the agent was last updated. Required."""
366    description: str
367    """An optional description of the agent's purpose or capabilities."""
368    isPublic: bool
369    """Whether the agent is publicly accessible; defaults to False."""
370    auditLog: bool
371    """Whether audit logging is enabled for the agent's activities; defaults to False."""
372    options: AiChatOptions
373    """The agent's default chat options, overridable by the user during use. Required."""
374    apiKey: str
375    """Optional API key used specifically for operations on this agent."""

A definition of an AI agent with its properties and default chat options.

Returned by AiClient.list_agents().

id: str

The unique identifier of the AI agent. Required.

createdAt: str

ISO 8601 timestamp of when the agent was created. Required.

updatedAt: str

ISO 8601 timestamp of when the agent was last updated. Required.

description: str

An optional description of the agent's purpose or capabilities.

isPublic: bool

Whether the agent is publicly accessible; defaults to False.

auditLog: bool

Whether audit logging is enabled for the agent's activities; defaults to False.

options: AiChatOptions

The agent's default chat options, overridable by the user during use. Required.

apiKey: str

Optional API key used specifically for operations on this agent.

class AiAgentExecutionPlanOptions(typing.TypedDict):
141class AiAgentExecutionPlanOptions(TypedDict, total=False):
142    """Options for AI agent execution plan."""
143
144    enabled: bool

Options for AI agent execution plan.

enabled: bool
class AiAgentMemoryOptions(typing.TypedDict):
67class AiAgentMemoryOptions(TypedDict, total=False):
68    """Memory/session configuration for agent chat."""
69
70    memoryId: str
71    """Unique memory ID. Reuse to continue a conversation."""
72    memoryMode: AiMemoryMode
73    """How memory is used: 'read-write', 'read-only', 'write-only', 'disabled'."""

Memory/session configuration for agent chat.

memoryId: str

Unique memory ID. Reuse to continue a conversation.

memoryMode: Literal['read-write', 'read-only', 'write-only', 'disabled']

How memory is used: 'read-write', 'read-only', 'write-only', 'disabled'.

AiAgentResponseFormat = typing.Literal['text', 'json_object'] | AiStructuredOutputFormat
class AiAudioCreateSpeechOptions(typing.TypedDict):
162class AiAudioCreateSpeechOptions(TypedDict, total=False):
163    """Options for text-to-speech."""
164
165    modelName: str
166    """'tts-1' or 'tts-1-hd'."""
167    voice: str
168    """'alloy'|'ash'|'ballad'|'coral'|'echo'|'fable'|'onyx'|'nova'|'sage'|'shimmer'|'verse'."""
169    responseFormat: str
170    """Audio output format."""
171    instructions: str
172    """Extra instructions for speech generation."""
173    speed: float
174    """Speech speed."""

Options for text-to-speech.

modelName: str

'tts-1' or 'tts-1-hd'.

voice: str

'alloy'|'ash'|'ballad'|'coral'|'echo'|'fable'|'onyx'|'nova'|'sage'|'shimmer'|'verse'.

responseFormat: str

Audio output format.

instructions: str

Extra instructions for speech generation.

speed: float

Speech speed.

AiChatModelSelection = str | IntegrationModelSpec
class AiChatOptions(typing.TypedDict):
177class AiChatOptions(TypedDict, total=False):
178    """Full chat options for AI agent ask/chat operations.
179
180    Mirrors BaseAiChatOptions from the TypeScript SDK.
181    All fields are optional.
182    """
183
184    model: AiChatModelSelection
185    """LLM model to use. String name or IntegrationModelSpec."""
186    maxTokens: int
187    """Max input tokens for the AI model."""
188    maxOutputTokens: int
189    """Max output tokens from the AI model."""
190    temperature: float
191    """Sampling temperature (default 0.5)."""
192    instructions: str
193    """Extra instructions to include with the prompt."""
194    functions: list[str]
195    """AI function IDs to expose to the agent."""
196    memoryOptions: AiAgentMemoryOptions
197    """Memory/session configuration."""
198    responseFormat: AiAgentResponseFormat
199    """Response format: 'text', 'json_object', or structured output."""
200    includeReference: bool
201    """Include source references from context."""
202    smoothTyping: bool
203    """Smooth typing effect for UI display (default true)."""
204    disableContext: bool
205    """Disable the whole context for this request."""
206    enablePromptRewriteForRag: bool
207    """Rewrite prompt for RAG (default false)."""
208    agentContext: dict[str, Any]
209    """Global context passed to agent and all AI functions."""
210    connectedAgents: list[AiConnectedAgentMetadata]
211    """Connected agents that can be called."""
212    connectedIntegrations: list[AiConnectedIntegrationMetadata]
213    """Connected integrations."""
214    connectedKnowledgeBases: list[AiConnectedKnowledgeBaseMetadata]
215    """Connected knowledge bases."""
216    guardrails: GuardrailsOptions
217    """Guardrail options."""
218    contextMetadataFilterForKnowledgeBase: dict[str, Any]
219    """Metadata filters per knowledge base ID."""
220    voiceOptions: AiAudioCreateSpeechOptions
221    """Options for voice response."""
222    quotas: AiChatPromptQuotas
223    """Budget for nested AI calls."""
224    executionPlanOptions: AiAgentExecutionPlanOptions
225    """Execution plan options."""
226    fileUrls: list[AiFileUrl]
227    """File URLs to include in context."""
228    fileIds: list[str]
229    """File IDs from AI provider's Files API."""
230    reasoningEffort: AiReasoningEffort
231    """Reasoning effort level."""
232    verbosity: AiVerbosityLevel
233    """Response verbosity level."""
234    useCodeInterpreter: Literal["none", "llm"]
235    """Enable LLM's built-in code interpreter."""
236    rerankProvider: AiRerankProvider
237    """Reranker provider for context (default 'cohere')."""
238    includeMetadata: bool
239    """Include metadata in context (deprecated)."""
240    timeoutMs: int
241    """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.

model: str | IntegrationModelSpec

LLM model to use. String name or IntegrationModelSpec.

maxTokens: int

Max input tokens for the AI model.

maxOutputTokens: int

Max output tokens from the AI model.

temperature: float

Sampling temperature (default 0.5).

instructions: str

Extra instructions to include with the prompt.

functions: list[str]

AI function IDs to expose to the agent.

memoryOptions: AiAgentMemoryOptions

Memory/session configuration.

responseFormat: Literal['text', 'json_object'] | AiStructuredOutputFormat

Response format: 'text', 'json_object', or structured output.

includeReference: bool

Include source references from context.

smoothTyping: bool

Smooth typing effect for UI display (default true).

disableContext: bool

Disable the whole context for this request.

enablePromptRewriteForRag: bool

Rewrite prompt for RAG (default false).

agentContext: dict[str, typing.Any]

Global context passed to agent and all AI functions.

connectedAgents: list[AiConnectedAgentMetadata]

Connected agents that can be called.

connectedIntegrations: list[AiConnectedIntegrationMetadata]

Connected integrations.

connectedKnowledgeBases: list[AiConnectedKnowledgeBaseMetadata]

Connected knowledge bases.

guardrails: GuardrailsOptions

Guardrail options.

contextMetadataFilterForKnowledgeBase: dict[str, typing.Any]

Metadata filters per knowledge base ID.

Options for voice response.

Budget for nested AI calls.

executionPlanOptions: AiAgentExecutionPlanOptions

Execution plan options.

fileUrls: list[AiFileUrl]

File URLs to include in context.

fileIds: list[str]

File IDs from AI provider's Files API.

reasoningEffort: Literal['minimal', 'low', 'medium', 'high']

Reasoning effort level.

verbosity: Literal['low', 'medium', 'high']

Response verbosity level.

useCodeInterpreter: Literal['none', 'llm']

Enable LLM's built-in code interpreter.

rerankProvider: Literal['cohere']

Reranker provider for context (default 'cohere').

includeMetadata: bool

Include metadata in context (deprecated).

timeoutMs: int

Request timeout in milliseconds (default 240000).

class AiChatPromptQuotas(typing.TypedDict):
135class AiChatPromptQuotas(TypedDict, total=False):
136    """Budget for nested/recursive AI chat calls."""
137
138    maxNestedCalls: int

Budget for nested/recursive AI chat calls.

maxNestedCalls: int
class AiClient:
 32class AiClient:
 33    """Entry point for AI operations: agents, knowledge base, audio, image.
 34
 35    Obtained via :meth:`Squid.ai()`.
 36
 37    Example::
 38
 39        ai = squid.ai()
 40        agent = ai.agent("my-agent")
 41        kb = ai.knowledge_base("my-kb")
 42        image_url = await ai.image().generate("a cat in space")
 43    """
 44
 45    def __init__(self, http: HttpTransport) -> None:
 46        self._http = http
 47
 48    def agent(self, agent_id: str) -> AgentClient:
 49        """Get a client for a specific AI agent.
 50
 51        Args:
 52            agent_id: The unique agent identifier.
 53
 54        Returns:
 55            An :class:`AgentClient` bound to the given agent ID.
 56        """
 57        return AgentClient(self._http, agent_id)
 58
 59    def knowledge_base(self, knowledge_base_id: str) -> KnowledgeBaseClient:
 60        """Get a client for a specific knowledge base.
 61
 62        Args:
 63            knowledge_base_id: The unique knowledge base identifier.
 64
 65        Returns:
 66            A :class:`KnowledgeBaseClient` bound to the given knowledge base ID.
 67        """
 68        return KnowledgeBaseClient(self._http, knowledge_base_id)
 69
 70    def image(self) -> ImageClient:
 71        """Get a client for image generation and processing.
 72
 73        Returns:
 74            An :class:`ImageClient` instance.
 75        """
 76        return ImageClient(self._http)
 77
 78    def audio(self) -> AudioClient:
 79        """Get a client for audio transcription and speech synthesis.
 80
 81        Returns:
 82            An :class:`AudioClient` instance.
 83        """
 84        return AudioClient(self._http)
 85
 86    async def list_agents(self) -> list[AiAgent]:
 87        """List all AI agents defined for the application.
 88
 89        Returns:
 90            A list of ``AiAgent`` dicts. Empty list if no agents are defined.
 91        """
 92        result = await self._http.get("squid-api/v1/ai/agent/listAgents")
 93        return result.get("agents", []) if result else []
 94
 95    async def list_knowledge_bases(self) -> list[AiKnowledgeBase]:
 96        """List all AI knowledge bases defined for the application.
 97
 98        Returns:
 99            A list of ``AiKnowledgeBase`` dicts. Empty list if no knowledge
100            bases are defined.
101        """
102        result = await self._http.get("squid-api/v1/ai/knowledge-base/listKnowledgeBases")
103        return result.get("knowledgeBases", []) if result else []
104
105    async def list_chat_models(self, include_deprecated: bool = False) -> list[ModelIdSpec]:
106        """List all AI chat models available to the application.
107
108        Includes both Squid-provided vendor models and any custom integration
109        models configured for the app.
110
111        Args:
112            include_deprecated: When True, deprecated vendor models are
113                included and marked with ``replacedBy``. Defaults to False.
114
115        Returns:
116            A list of ``ModelIdSpec`` dicts, each with ``modelId``, an optional
117            ``integrationId``, and a human-readable ``displayName``. Vendor
118            models also carry a ``description``, and deprecated vendor models a
119            ``replacedBy`` with the active model their calls are routed to.
120        """
121        params = {"includeDeprecated": "true"} if include_deprecated else None
122        result = await self._http.get("squid-api/v1/ai/settings/listChatModels", params=params)
123        return result.get("models", []) if result else []
124
125    async def list_functions(self) -> list[AiFunctionMetadata]:
126        """List all AI functions registered for the application's deployed bundle.
127
128        Returns:
129            A list of ``AiFunctionMetadata`` dicts. Empty list if no functions
130            are registered.
131        """
132        result = await self._http.get("squid-api/v1/ai/function/listFunctions")
133        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")
AiClient(http: squidcloud.http.HttpTransport)
45    def __init__(self, http: HttpTransport) -> None:
46        self._http = http
def agent(self, agent_id: str) -> AgentClient:
48    def agent(self, agent_id: str) -> AgentClient:
49        """Get a client for a specific AI agent.
50
51        Args:
52            agent_id: The unique agent identifier.
53
54        Returns:
55            An :class:`AgentClient` bound to the given agent ID.
56        """
57        return AgentClient(self._http, agent_id)

Get a client for a specific AI agent.

Arguments:
  • agent_id: The unique agent identifier.
Returns:

An AgentClient bound to the given agent ID.

def knowledge_base(self, knowledge_base_id: str) -> KnowledgeBaseClient:
59    def knowledge_base(self, knowledge_base_id: str) -> KnowledgeBaseClient:
60        """Get a client for a specific knowledge base.
61
62        Args:
63            knowledge_base_id: The unique knowledge base identifier.
64
65        Returns:
66            A :class:`KnowledgeBaseClient` bound to the given knowledge base ID.
67        """
68        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 KnowledgeBaseClient bound to the given knowledge base ID.

def image(self) -> ImageClient:
70    def image(self) -> ImageClient:
71        """Get a client for image generation and processing.
72
73        Returns:
74            An :class:`ImageClient` instance.
75        """
76        return ImageClient(self._http)

Get a client for image generation and processing.

Returns:

An ImageClient instance.

def audio(self) -> AudioClient:
78    def audio(self) -> AudioClient:
79        """Get a client for audio transcription and speech synthesis.
80
81        Returns:
82            An :class:`AudioClient` instance.
83        """
84        return AudioClient(self._http)

Get a client for audio transcription and speech synthesis.

Returns:

An AudioClient instance.

async def list_agents(self) -> list[AiAgent]:
86    async def list_agents(self) -> list[AiAgent]:
87        """List all AI agents defined for the application.
88
89        Returns:
90            A list of ``AiAgent`` dicts. Empty list if no agents are defined.
91        """
92        result = await self._http.get("squid-api/v1/ai/agent/listAgents")
93        return result.get("agents", []) if result else []

List all AI agents defined for the application.

Returns:

A list of AiAgent dicts. Empty list if no agents are defined.

async def list_knowledge_bases(self) -> list[AiKnowledgeBase]:
 95    async def list_knowledge_bases(self) -> list[AiKnowledgeBase]:
 96        """List all AI knowledge bases defined for the application.
 97
 98        Returns:
 99            A list of ``AiKnowledgeBase`` dicts. Empty list if no knowledge
100            bases are defined.
101        """
102        result = await self._http.get("squid-api/v1/ai/knowledge-base/listKnowledgeBases")
103        return result.get("knowledgeBases", []) if result else []

List all AI knowledge bases defined for the application.

Returns:

A list of AiKnowledgeBase dicts. Empty list if no knowledge bases are defined.

async def list_chat_models( self, include_deprecated: bool = False) -> list[ModelIdSpec]:
105    async def list_chat_models(self, include_deprecated: bool = False) -> list[ModelIdSpec]:
106        """List all AI chat models available to the application.
107
108        Includes both Squid-provided vendor models and any custom integration
109        models configured for the app.
110
111        Args:
112            include_deprecated: When True, deprecated vendor models are
113                included and marked with ``replacedBy``. Defaults to False.
114
115        Returns:
116            A list of ``ModelIdSpec`` dicts, each with ``modelId``, an optional
117            ``integrationId``, and a human-readable ``displayName``. Vendor
118            models also carry a ``description``, and deprecated vendor models a
119            ``replacedBy`` with the active model their calls are routed to.
120        """
121        params = {"includeDeprecated": "true"} if include_deprecated else None
122        result = await self._http.get("squid-api/v1/ai/settings/listChatModels", params=params)
123        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 ModelIdSpec dicts, each with modelId, an optional integrationId, and a human-readable displayName. Vendor models also carry a description, and deprecated vendor models a replacedBy with the active model their calls are routed to.

async def list_functions(self) -> list[AiFunctionMetadata]:
125    async def list_functions(self) -> list[AiFunctionMetadata]:
126        """List all AI functions registered for the application's deployed bundle.
127
128        Returns:
129            A list of ``AiFunctionMetadata`` dicts. Empty list if no functions
130            are registered.
131        """
132        result = await self._http.get("squid-api/v1/ai/function/listFunctions")
133        return result.get("functions", []) if result else []

List all AI functions registered for the application's deployed bundle.

Returns:

A list of AiFunctionMetadata dicts. Empty list if no functions are registered.

class AiConnectedAgentMetadata(typing.TypedDict):
76class AiConnectedAgentMetadata(TypedDict):
77    """Metadata for a connected agent."""
78
79    agentId: str
80    description: str

Metadata for a connected agent.

agentId: str
description: str
class AiConnectedIntegrationMetadata(typing.TypedDict):
 83class AiConnectedIntegrationMetadata(TypedDict, total=False):
 84    """Metadata for a connected integration.
 85
 86    ``integrationId`` and ``integrationType`` are required by the platform API;
 87    the remaining fields are optional.
 88    """
 89
 90    integrationId: str
 91    """The ID of the connected integration. Required."""
 92    integrationType: str
 93    """The integration type, e.g. 'hubspot', 'slack', 'api'. Required."""
 94    description: str
 95    """Optional description used as the AI function description for the parent agent."""
 96    instructions: str
 97    """Optional instructions for the connected integration agent, overriding the default."""
 98    functionsToUse: list[str]
 99    """AI function IDs the agent may use. Omit for all functions; [] for none."""
100    options: dict[str, Any]
101    """Additional integration options interpreted by Squid Core or connector AI functions."""
102    connectedAsMcp: bool
103    """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.

integrationId: str

The ID of the connected integration. Required.

integrationType: str

The integration type, e.g. 'hubspot', 'slack', 'api'. Required.

description: str

Optional description used as the AI function description for the parent agent.

instructions: str

Optional instructions for the connected integration agent, overriding the default.

functionsToUse: list[str]

AI function IDs the agent may use. Omit for all functions; [] for none.

options: dict[str, typing.Any]

Additional integration options interpreted by Squid Core or connector AI functions.

connectedAsMcp: bool

Treat this integration as an MCP server (API integrations with exposeAsMcpServer).

class AiConnectedKnowledgeBaseMetadata(typing.TypedDict):
106class AiConnectedKnowledgeBaseMetadata(TypedDict, total=False):
107    """Metadata for a connected knowledge base."""
108
109    knowledgeBaseId: str
110    description: str
111    includeMetadata: bool

Metadata for a connected knowledge base.

knowledgeBaseId: str
description: str
includeMetadata: bool
class AiContextFileOptions(typing.TypedDict):
450class AiContextFileOptions(TypedDict, total=False):
451    """Options for file context processing."""
452
453    chunkOverlap: int
454    ragType: str

Options for file context processing.

chunkOverlap: int
ragType: str
class AiContextTextOptions(typing.TypedDict):
430class AiContextTextOptions(TypedDict, total=False):
431    """Options for text context processing."""
432
433    chunkOverlap: int
434    """Amount of chunk overlap in characters."""
435    ragType: str
436    """The type of RAG to use."""

Options for text context processing.

chunkOverlap: int

Amount of chunk overlap in characters.

ragType: str

The type of RAG to use.

AiEmbeddingsModelSelection = str | IntegrationEmbeddingModelSpec
class AiFileUrl(typing.TypedDict):
114class AiFileUrl(TypedDict, total=False):
115    """File URL to include in chat context."""
116
117    id: str
118    type: str
119    purpose: str
120    url: str
121    description: str
122    fileName: str

File URL to include in chat context.

id: str
type: str
purpose: str
url: str
description: str
fileName: str
class AiFunctionAttributes(typing.TypedDict):
515class AiFunctionAttributes(TypedDict, total=False):
516    """Additional optional readonly metadata for an AI function."""
517
518    integrationType: list[str]
519    """Types of integration this function is used for. Functions with a defined
520    'integrationType' require 'integrationId' to be passed as part of the function context."""

Additional optional readonly metadata for an AI function.

integrationType: list[str]

Types of integration this function is used for. Functions with a defined 'integrationType' require 'integrationId' to be passed as part of the function context.

class AiFunctionMetadata(typing.TypedDict):
523class AiFunctionMetadata(TypedDict, total=False):
524    """Metadata describing an AI function available in the application.
525
526    Returned by :meth:`AiClient.list_functions`.
527    """
528
529    serviceFunction: str
530    """The fully qualified name of the function ('ServiceName:functionName'). Required."""
531    description: str
532    """Description of what the function does."""
533    promptId: str
534    """Opaque ID of a registered prompt that supplies this function's description;
535    resolved server-side."""
536    params: list[AiFunctionParam]
537    """Parameters that the function accepts. Required."""
538    attributes: AiFunctionAttributes
539    """Additional attributes for the function."""
540    categories: list[str]
541    """Categories this function belongs to."""
542    internal: bool
543    """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().

serviceFunction: str

The fully qualified name of the function ('ServiceName:functionName'). Required.

description: str

Description of what the function does.

promptId: str

Opaque ID of a registered prompt that supplies this function's description; resolved server-side.

params: list[AiFunctionParam]

Parameters that the function accepts. Required.

attributes: AiFunctionAttributes

Additional attributes for the function.

categories: list[str]

Categories this function belongs to.

internal: bool

Whether this function is internal and not meant for direct use.

class AiFunctionParam(typing.TypedDict):
500class AiFunctionParam(TypedDict, total=False):
501    """Defines the structure of a parameter for an AI function."""
502
503    name: str
504    """Name of the parameter. Required."""
505    description: str
506    """Description of the parameter's purpose. Required."""
507    type: AiFunctionParamType
508    """Data type of the parameter. Required."""
509    required: bool
510    """Indicates if the parameter is mandatory. Required."""
511    enum: list[str]
512    """List of possible values for the parameter, if applicable."""

Defines the structure of a parameter for an AI function.

name: str

Name of the parameter. Required.

description: str

Description of the parameter's purpose. Required.

type: Literal['string', 'number', 'boolean', 'date', 'files']

Data type of the parameter. Required.

required: bool

Indicates if the parameter is mandatory. Required.

enum: list[str]

List of possible values for the parameter, if applicable.

class AiKnowledgeBase(typing.TypedDict):
405class AiKnowledgeBase(TypedDict, total=False):
406    """An AI knowledge base that can be attached to an AI agent.
407
408    Returned by :meth:`AiClient.list_knowledge_bases`.
409    """
410
411    id: str
412    """The unique identifier of the knowledge base. Required."""
413    appId: str
414    """The app ID that the knowledge base belongs to. Required."""
415    description: str
416    """The user's description of the knowledge base. Required."""
417    metadataFields: list[AiKnowledgeBaseMetadataField]
418    """Predefined metadata fields that can be used for filtering. Required."""
419    embeddingModel: AiEmbeddingsModelSelection
420    """The embedding model used by this knowledge base. Required."""
421    chatModel: AiChatModelSelection
422    """The model used when asking questions of this knowledge base. Required."""
423    vectorDbType: Literal["postgres", "mongoAtlas"]
424    """The vector store backend the knowledge base reads/writes from. Set at creation
425    and immutable thereafter. Absent on older records."""
426    updatedAt: str
427    """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().

id: str

The unique identifier of the knowledge base. Required.

appId: str

The app ID that the knowledge base belongs to. Required.

description: str

The user's description of the knowledge base. Required.

metadataFields: list[AiKnowledgeBaseMetadataField]

Predefined metadata fields that can be used for filtering. Required.

embeddingModel: str | IntegrationEmbeddingModelSpec

The embedding model used by this knowledge base. Required.

chatModel: str | IntegrationModelSpec

The model used when asking questions of this knowledge base. Required.

vectorDbType: Literal['postgres', 'mongoAtlas']

The vector store backend the knowledge base reads/writes from. Set at creation and immutable thereafter. Absent on older records.

updatedAt: str

ISO 8601 timestamp of when the knowledge base was last updated. Required.

class AiKnowledgeBaseMetadataField(typing.TypedDict):
381class AiKnowledgeBaseMetadataField(TypedDict, total=False):
382    """Metadata field definition for a knowledge base."""
383
384    name: str
385    dataType: str
386    required: bool
387    description: str

Metadata field definition for a knowledge base.

name: str
dataType: str
required: bool
description: str
class AiQueryAnalyzeResultsOptions(typing.TypedDict):
288class AiQueryAnalyzeResultsOptions(TypedDict, total=False):
289    """Options for the result-analysis stage of AI query."""
290
291    disabled: bool
292    """When true, skip analysis and return raw results only."""
293    enableCodeInterpreter: bool
294    """Enable code interpreter mode (default false)."""
295    aiOptions: AiChatOptions
296    """Customize AI agent behavior used by the stage."""
297    agentId: AiAgentId
298    """If set, use this agent to analyze results and produce the final answer."""

Options for the result-analysis stage of AI query.

disabled: bool

When true, skip analysis and return raw results only.

enableCodeInterpreter: bool

Enable code interpreter mode (default false).

aiOptions: AiChatOptions

Customize AI agent behavior used by the stage.

agentId: str

If set, use this agent to analyze results and produce the final answer.

AiQueryCollectionsSelectionRunMode = typing.Literal['default', 'force', 'disable']
class AiQueryGenerateQueryOptions(typing.TypedDict):
274class AiQueryGenerateQueryOptions(TypedDict, total=False):
275    """Options for the query-generation stage of AI query."""
276
277    aiOptions: AiChatOptions
278    """Customize AI agent behavior used by the stage."""
279    maxErrorCorrections: int
280    """Number of retries due to errors in a generated AI query (default 2)."""
281    agentId: AiAgentId
282    """If set, use this agent to generate the query."""
283    allowClarification: bool
284    """When true, allow the AI to ask a clarifying question instead of
285    generating a query for ambiguous prompts (default false)."""

Options for the query-generation stage of AI query.

aiOptions: AiChatOptions

Customize AI agent behavior used by the stage.

maxErrorCorrections: int

Number of retries due to errors in a generated AI query (default 2).

agentId: str

If set, use this agent to generate the query.

allowClarification: bool

When true, allow the AI to ask a clarifying question instead of generating a query for ambiguous prompts (default false).

class AiQueryOptions(typing.TypedDict):
310class AiQueryOptions(TypedDict, total=False):
311    """Options for configuring AI query execution.
312
313    Mirrors ``AiQueryOptions`` from the TypeScript SDK. All fields optional.
314    """
315
316    instructions: str
317    """Custom instructions applied to all stages unless overridden per-stage."""
318    enableRawResults: bool
319    """Enable raw results output."""
320    selectCollectionsOptions: AiQuerySelectCollectionsOptions
321    """Collection-selection stage options."""
322    generateQueryOptions: AiQueryGenerateQueryOptions
323    """Query-generation stage options."""
324    analyzeResultsOptions: AiQueryAnalyzeResultsOptions
325    """Result-analysis stage options."""
326    sessionContext: AiSessionContext
327    """Session information (``agentId`` may be omitted)."""
328    memoryOptions: AiAgentMemoryOptions
329    """Memory/session configuration."""
330    generateQueriesOnly: bool
331    """If true, return generated queries without executing or analyzing them."""
332    validateWithAiOptions: AiQueryValidateWithAiOptions
333    """Optional AI validation of generated queries."""

Options for configuring AI query execution.

Mirrors AiQueryOptions from the TypeScript SDK. All fields optional.

instructions: str

Custom instructions applied to all stages unless overridden per-stage.

enableRawResults: bool

Enable raw results output.

selectCollectionsOptions: AiQuerySelectCollectionsOptions

Collection-selection stage options.

generateQueryOptions: AiQueryGenerateQueryOptions

Query-generation stage options.

analyzeResultsOptions: AiQueryAnalyzeResultsOptions

Result-analysis stage options.

sessionContext: AiSessionContext

Session information (agentId may be omitted).

memoryOptions: AiAgentMemoryOptions

Memory/session configuration.

generateQueriesOnly: bool

If true, return generated queries without executing or analyzing them.

validateWithAiOptions: AiQueryValidateWithAiOptions

Optional AI validation of generated queries.

class AiQuerySelectCollectionsOptions(typing.TypedDict):
263class AiQuerySelectCollectionsOptions(TypedDict, total=False):
264    """Options for the collection-selection stage of AI query."""
265
266    collectionsToUse: list[str]
267    """Restrict query to these collections. Defaults to all collections."""
268    runMode: AiQueryCollectionsSelectionRunMode
269    """Stage behavior: 'default', 'force', or 'disable'."""
270    aiOptions: AiChatOptions
271    """Customize AI agent behavior used by the stage."""

Options for the collection-selection stage of AI query.

collectionsToUse: list[str]

Restrict query to these collections. Defaults to all collections.

runMode: Literal['default', 'force', 'disable']

Stage behavior: 'default', 'force', or 'disable'.

aiOptions: AiChatOptions

Customize AI agent behavior used by the stage.

class AiQueryValidateWithAiOptions(typing.TypedDict):
301class AiQueryValidateWithAiOptions(TypedDict, total=False):
302    """Options for AI-based validation of generated queries."""
303
304    enabled: bool
305    """Whether AI validation is enabled."""
306    aiOptions: AiChatOptions
307    """Defaults to the same model used for query generation."""

Options for AI-based validation of generated queries.

enabled: bool

Whether AI validation is enabled.

aiOptions: AiChatOptions

Defaults to the same model used for query generation.

class AiSessionContext(typing.TypedDict):
250class AiSessionContext(TypedDict, total=False):
251    """Session context for AI query execution.
252
253    Mirrors the TypeScript ``AiSessionContext`` type. All fields optional
254    here because the query endpoint accepts a partial context (``agentId``
255    may be omitted).
256    """
257
258    clientId: str
259    agentId: str
260    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).

clientId: str
agentId: str
jobId: str
class AiStructuredOutputFormat(typing.TypedDict):
125class AiStructuredOutputFormat(TypedDict):
126    """Structured output format for JSON responses."""
127
128    type: Literal["json_schema"]
129    schema: dict[str, Any]

Structured output format for JSON responses.

type: Literal['json_schema']
schema: dict[str, typing.Any]
class AudioClient:
718class AudioClient:
719    """Audio transcription and speech synthesis.
720
721    Obtained via :meth:`AiClient.audio`.
722
723    Example::
724
725        text = await squid.ai().audio().transcribe(audio_bytes)
726        speech = await squid.ai().audio().create_speech("Hello!", options={"voice": "nova"})
727    """
728
729    def __init__(self, http: HttpTransport) -> None:
730        self._http = http
731
732    async def transcribe(
733        self,
734        audio_data: bytes,
735        filename: str = "audio.wav",
736        content_type: str = "audio/wav",
737        *,
738        options: dict[str, Any] | None = None,
739    ) -> str:
740        """Transcribe audio to text.
741
742        Args:
743            audio_data: The audio file content as bytes.
744            filename: The filename (used in the multipart upload).
745            content_type: The MIME type of the audio file.
746            options: Provider-specific transcription options.
747
748        Returns:
749            The transcribed text.
750        """
751        form_data: dict[str, str] = {
752            "optionsJson": json.dumps(options or {}),
753        }
754        result = await self._http.post_form(
755            "squid-api/v1/ai/audio/transcribe",
756            data=form_data,
757            files=[("file", (filename, audio_data, content_type))],
758        )
759        return result if isinstance(result, str) else str(result)
760
761    async def create_speech(
762        self,
763        text: str,
764        options: AiAudioCreateSpeechOptions,
765    ) -> bytes:
766        """Generate speech audio from text.
767
768        Args:
769            text: The text to convert to speech.
770            options: Speech generation options. See :class:`AiAudioCreateSpeechOptions`.
771                Required keys: ``modelName`` (e.g., ``'tts-1'``), ``voice``
772                (e.g., ``'nova'``, ``'alloy'``).
773
774        Returns:
775            Raw audio file bytes (e.g., MP3 format by default).
776
777        Example::
778
779            audio_data = (
780                await squid.ai()
781                .audio()
782                .create_speech(
783                    "Hello!",
784                    options={
785                        "modelName": "tts-1",
786                        "voice": "nova",
787                    },
788                )
789            )
790            with open("speech.mp3", "wb") as f:
791                f.write(audio_data)
792        """
793        return await self._http.post(
794            "squid-api/v1/ai/audio/createSpeech",
795            {"input": text, "options": options},
796        )

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"})
AudioClient(http: squidcloud.http.HttpTransport)
729    def __init__(self, http: HttpTransport) -> None:
730        self._http = http
async def transcribe( self, audio_data: bytes, filename: str = 'audio.wav', content_type: str = 'audio/wav', *, options: dict[str, Any] | None = None) -> str:
732    async def transcribe(
733        self,
734        audio_data: bytes,
735        filename: str = "audio.wav",
736        content_type: str = "audio/wav",
737        *,
738        options: dict[str, Any] | None = None,
739    ) -> str:
740        """Transcribe audio to text.
741
742        Args:
743            audio_data: The audio file content as bytes.
744            filename: The filename (used in the multipart upload).
745            content_type: The MIME type of the audio file.
746            options: Provider-specific transcription options.
747
748        Returns:
749            The transcribed text.
750        """
751        form_data: dict[str, str] = {
752            "optionsJson": json.dumps(options or {}),
753        }
754        result = await self._http.post_form(
755            "squid-api/v1/ai/audio/transcribe",
756            data=form_data,
757            files=[("file", (filename, audio_data, content_type))],
758        )
759        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.

async def create_speech( self, text: str, options: AiAudioCreateSpeechOptions) -> bytes:
761    async def create_speech(
762        self,
763        text: str,
764        options: AiAudioCreateSpeechOptions,
765    ) -> bytes:
766        """Generate speech audio from text.
767
768        Args:
769            text: The text to convert to speech.
770            options: Speech generation options. See :class:`AiAudioCreateSpeechOptions`.
771                Required keys: ``modelName`` (e.g., ``'tts-1'``), ``voice``
772                (e.g., ``'nova'``, ``'alloy'``).
773
774        Returns:
775            Raw audio file bytes (e.g., MP3 format by default).
776
777        Example::
778
779            audio_data = (
780                await squid.ai()
781                .audio()
782                .create_speech(
783                    "Hello!",
784                    options={
785                        "modelName": "tts-1",
786                        "voice": "nova",
787                    },
788                )
789            )
790            with open("speech.mp3", "wb") as f:
791                f.write(audio_data)
792        """
793        return await self._http.post(
794            "squid-api/v1/ai/audio/createSpeech",
795            {"input": text, "options": options},
796        )

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)
class CreatePdfDimensionsOptions(typing.TypedDict):
652class CreatePdfDimensionsOptions(TypedDict):
653    """PDF output options by custom dimensions."""
654
655    type: Literal["dimensions"]
656    width: int
657    """Width in pixels."""
658    height: int
659    """Height in pixels."""

PDF output options by custom dimensions.

type: Literal['dimensions']
width: int

Width in pixels.

height: int

Height in pixels.

class CreatePdfFormatOptions(typing.TypedDict):
633class CreatePdfFormatOptions(TypedDict):
634    """PDF output options by format."""
635
636    type: Literal["format"]
637    format: Literal[
638        "letter",
639        "legal",
640        "tabloid",
641        "ledger",
642        "a0",
643        "a1",
644        "a2",
645        "a3",
646        "a4",
647        "a5",
648        "a6",
649    ]

PDF output options by format.

type: Literal['format']
format: Literal['letter', 'legal', 'tabloid', 'ledger', 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6']
class ExtractDataFromDocumentOptions(typing.TypedDict):
665class ExtractDataFromDocumentOptions(TypedDict, total=False):
666    """Options for document data extraction."""
667
668    extractImages: bool
669    """Whether to extract embedded images."""
670    imageMinSizePixels: int
671    """Minimum image size to extract."""
672    pageIndexes: list[int]
673    """Specific pages to extract (0-based)."""
674    preferredExtractionMethod: str
675    discardOriginalFile: bool

Options for document data extraction.

extractImages: bool

Whether to extract embedded images.

imageMinSizePixels: int

Minimum image size to extract.

pageIndexes: list[int]

Specific pages to extract (0-based).

preferredExtractionMethod: str
discardOriginalFile: bool
class ExtractionClient:
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.

ExtractionClient(http: squidcloud.http.HttpTransport)
20    def __init__(self, http: HttpTransport) -> None:
21        self._http = http
async def create_pdf_from_html( self, inner_html: str, *, title: str | None = None, css_url: str | None = None, output_options: CreatePdfFormatOptions | CreatePdfDimensionsOptions | None = None) -> dict:
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'.

async def create_pdf_from_url( self, url: str, *, title: str | None = None, output_options: CreatePdfFormatOptions | CreatePdfDimensionsOptions | None = None) -> dict:
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'.

async def extract_data_from_document_url( self, url: str, options: ExtractDataFromDocumentOptions | None = None) -> dict:
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'.

async def extract_data_from_document_file( self, file_data: bytes, filename: str, content_type: str = 'application/pdf', options: ExtractDataFromDocumentOptions | None = None) -> dict:
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'.

class FileContextRequest(typing.TypedDict):
457class FileContextRequest(TypedDict, total=False):
458    """Request to upsert a file context."""
459
460    contextId: str
461    type: Literal["file"]
462    metadata: dict[str, Any]
463    extractImages: bool
464    imageMinSizePixels: int
465    extractionModel: AiChatModelSelection
466    options: AiContextFileOptions
467    preferredExtractionMethod: str
468    discardOriginalFile: bool

Request to upsert a file context.

contextId: str
type: Literal['file']
metadata: dict[str, typing.Any]
extractImages: bool
imageMinSizePixels: int
extractionModel: str | IntegrationModelSpec
preferredExtractionMethod: str
discardOriginalFile: bool
class FluxOptions(typing.TypedDict):
565class FluxOptions(TypedDict, total=False):
566    """Options for Flux image generation."""
567
568    modelName: Literal["flux-pro-1.1", "flux-kontext-pro"]
569    width: int
570    """Must be multiple of 32, min 256, max 1440."""
571    height: int
572    """Must be multiple of 32, min 256, max 1440."""
573    prompt_upsampling: bool
574    seed: int
575    safety_tolerance: int
576    """1 (strict) to 5 (permissive)."""

Options for Flux image generation.

modelName: Literal['flux-pro-1.1', 'flux-kontext-pro']
width: int

Must be multiple of 32, min 256, max 1440.

height: int

Must be multiple of 32, min 256, max 1440.

prompt_upsampling: bool
seed: int
safety_tolerance: int

1 (strict) to 5 (permissive).

class GptImageOptions(typing.TypedDict):
549class GptImageOptions(TypedDict, total=False):
550    """Options for OpenAI gpt-image-* family image generation."""
551
552    modelName: Literal[
553        "gpt-image-1",
554        "gpt-image-1-mini",
555        "gpt-image-1.5",
556        "gpt-image-2",
557        "gpt-image-2-2026-04-21",
558        "chatgpt-image-latest",
559    ]
560    quality: Literal["auto", "high", "medium", "low"]
561    size: Literal["1024x1024", "1024x1536", "1536x1024", "auto"]
562    numberOfImagesToGenerate: int

Options for OpenAI gpt-image-* family image generation.

modelName: Literal['gpt-image-1', 'gpt-image-1-mini', 'gpt-image-1.5', 'gpt-image-2', 'gpt-image-2-2026-04-21', 'chatgpt-image-latest']
quality: Literal['auto', 'high', 'medium', 'low']
size: Literal['1024x1024', '1024x1536', '1536x1024', 'auto']
numberOfImagesToGenerate: int
class GuardrailsOptions(typing.TypedDict):
147class GuardrailsOptions(TypedDict, total=False):
148    """Guardrail options for agent responses."""
149
150    custom: str
151    """A custom guardrail instruction."""
152    disablePii: bool
153    """Disables personally identifiable information if true."""
154    professionalTone: bool
155    """Enforces a professional tone if true."""
156    offTopicAnswers: bool
157    """Prevents off-topic answers if true."""
158    disableProfanity: bool
159    """Disables profanity if true."""

Guardrail options for agent responses.

custom: str

A custom guardrail instruction.

disablePii: bool

Disables personally identifiable information if true.

professionalTone: bool

Enforces a professional tone if true.

offTopicAnswers: bool

Prevents off-topic answers if true.

disableProfanity: bool

Disables profanity if true.

class ImageClient:
644class ImageClient:
645    """Image generation and processing.
646
647    Supports DALL-E, Stable Diffusion Core, and Flux models.
648
649    Obtained via :meth:`AiClient.image`.
650
651    Example::
652
653        image_url = (
654            await squid.ai()
655            .image()
656            .generate(
657                "a cat astronaut on the moon",
658                options={"modelName": "gpt-image-1", "quality": "high"},
659            )
660        )
661    """
662
663    def __init__(self, http: HttpTransport) -> None:
664        self._http = http
665
666    async def generate(
667        self,
668        prompt: str,
669        options: ImageGenerateOptions | None = None,
670    ) -> str:
671        """Generate an image from a text prompt.
672
673        Args:
674            prompt: A text description of the image to generate.
675            options: Provider-specific generation options. Use one of:
676                - :class:`GptImageOptions`: ``{'modelName': 'gpt-image-1', 'quality': 'high', 'size': '1024x1024'}``
677                - :class:`FluxOptions`: ``{'modelName': 'flux-pro-1.1', 'width': 1024, 'height': 768}``
678                - :class:`StableDiffusionOptions`: ``{'modelName': 'stable-diffusion-core', 'aspectRatio': '16:9'}``
679
680        Returns:
681            The URL of the generated image.
682        """
683        result = await self._http.post(
684            "squid-api/v1/ai/image/generate",
685            {"prompt": prompt, "options": options or {}},
686        )
687        return result if isinstance(result, str) else str(result)
688
689    async def remove_background(
690        self,
691        image_data: bytes,
692        filename: str = "image.png",
693        content_type: str = "image/png",
694    ) -> str:
695        """Remove the background from an image.
696
697        Args:
698            image_data: The image file content as bytes.
699            filename: The filename (used in the multipart upload).
700            content_type: The MIME type of the image.
701
702        Returns:
703            The URL of the processed image with the background removed.
704        """
705        result = await self._http.post_form(
706            "squid-api/v1/ai/image/removeBackground",
707            data={},
708            files=[("file", (filename, image_data, content_type))],
709        )
710        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"},
    )
)
ImageClient(http: squidcloud.http.HttpTransport)
663    def __init__(self, http: HttpTransport) -> None:
664        self._http = http
async def generate( self, prompt: str, options: GptImageOptions | FluxOptions | StableDiffusionOptions | None = None) -> str:
666    async def generate(
667        self,
668        prompt: str,
669        options: ImageGenerateOptions | None = None,
670    ) -> str:
671        """Generate an image from a text prompt.
672
673        Args:
674            prompt: A text description of the image to generate.
675            options: Provider-specific generation options. Use one of:
676                - :class:`GptImageOptions`: ``{'modelName': 'gpt-image-1', 'quality': 'high', 'size': '1024x1024'}``
677                - :class:`FluxOptions`: ``{'modelName': 'flux-pro-1.1', 'width': 1024, 'height': 768}``
678                - :class:`StableDiffusionOptions`: ``{'modelName': 'stable-diffusion-core', 'aspectRatio': '16:9'}``
679
680        Returns:
681            The URL of the generated image.
682        """
683        result = await self._http.post(
684            "squid-api/v1/ai/image/generate",
685            {"prompt": prompt, "options": options or {}},
686        )
687        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.

async def remove_background( self, image_data: bytes, filename: str = 'image.png', content_type: str = 'image/png') -> str:
689    async def remove_background(
690        self,
691        image_data: bytes,
692        filename: str = "image.png",
693        content_type: str = "image/png",
694    ) -> str:
695        """Remove the background from an image.
696
697        Args:
698            image_data: The image file content as bytes.
699            filename: The filename (used in the multipart upload).
700            content_type: The MIME type of the image.
701
702        Returns:
703            The URL of the processed image with the background removed.
704        """
705        result = await self._http.post_form(
706            "squid-api/v1/ai/image/removeBackground",
707            data={},
708            files=[("file", (filename, image_data, content_type))],
709        )
710        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.

class IntegrationEmbeddingModelSpec(typing.TypedDict):
390class IntegrationEmbeddingModelSpec(TypedDict):
391    """Specifies an embedding model from a specific integration."""
392
393    integrationId: str
394    """The ID of the integration providing the embedding model."""
395    model: str
396    """The model name as recognized by the provider."""
397    dimensions: int
398    """The number of dimensions in the embedding vector output."""

Specifies an embedding model from a specific integration.

integrationId: str

The ID of the integration providing the embedding model.

model: str

The model name as recognized by the provider.

dimensions: int

The number of dimensions in the embedding vector output.

class IntegrationModelSpec(typing.TypedDict):
30class IntegrationModelSpec(TypedDict):
31    """Specifies a model from a specific integration."""
32
33    integrationId: str
34    model: str

Specifies a model from a specific integration.

integrationId: str
model: str
class KnowledgeBaseClient:
405class KnowledgeBaseClient:
406    """Operations on a single knowledge base.
407
408    Provides methods for managing knowledge base configuration, upserting
409    and searching text/file contexts, and retrieving individual contexts.
410
411    Obtained via :meth:`AiClient.knowledge_base`.
412
413    Example::
414
415        kb = squid.ai().knowledge_base("my-kb")
416        await kb.upsert(description="Product documentation")
417        await kb.upsert_contexts(
418            [
419                {
420                    "contextId": "doc-1",
421                    "type": "text",
422                    "title": "Getting Started",
423                    "text": "Welcome to our product...",
424                }
425            ]
426        )
427        results = await kb.search("How do I get started?")
428    """
429
430    def __init__(self, http: HttpTransport, kb_id: str) -> None:
431        self._http = http
432        self._kb_id = kb_id
433
434    async def get(self) -> dict | None:
435        """Get the knowledge base details.
436
437        Returns:
438            An ``AiKnowledgeBase`` dict with keys: ``id``, ``appId``,
439            ``description``, ``metadataFields``, ``embeddingModel``,
440            ``chatModel``, ``updatedAt``. Returns ``None`` if not found.
441        """
442        return await self._http.get(f"squid-api/v1/ai/knowledge-base/get/{self._kb_id}")
443
444    async def upsert(
445        self,
446        *,
447        description: str | None = None,
448        metadata_fields: list[AiKnowledgeBaseMetadataField] | None = None,
449        embedding_model: str | None = None,
450        chat_model: AiChatModelSelection | None = None,
451        name: str | None = None,
452    ) -> None:
453        """Create or update the knowledge base.
454
455        Args:
456            description: Description of the knowledge base's content.
457            metadata_fields: Schema for metadata fields used in filtering.
458                Each field: ``{'name': str, 'dataType': str, 'required': bool, 'description'?: str}``.
459            embedding_model: The embedding model name for vectorization.
460            chat_model: The LLM model for answering questions over this KB.
461            name: Display name for the knowledge base.
462        """
463        kb: dict[str, Any] = {"id": self._kb_id}
464        if description is not None:
465            kb["description"] = description
466        if metadata_fields is not None:
467            kb["metadataFields"] = metadata_fields
468        if embedding_model is not None:
469            kb["embeddingModel"] = embedding_model
470        if chat_model is not None:
471            kb["chatModel"] = chat_model
472        if name is not None:
473            kb["name"] = name
474        await self._http.post("squid-api/v1/ai/knowledge-base/upsert", {"knowledgeBase": kb})
475
476    async def delete(self) -> None:
477        """Delete the knowledge base and all its contexts permanently."""
478        await self._http.post("squid-api/v1/ai/knowledge-base/delete", {"id": self._kb_id})
479
480    # --- Contexts ---
481
482    async def get_context(self, context_id: str) -> dict | None:
483        """Get a specific context entry.
484
485        Args:
486            context_id: The unique context identifier.
487
488        Returns:
489            An ``AiKnowledgeBaseContext`` dict with keys: ``id``, ``appId``,
490            ``knowledgeBaseId``, ``createdAt``, ``updatedAt``, ``type``,
491            ``title``, ``text``, ``preview``, ``sizeBytes``, ``metadata``,
492            ``requestConfig``. Returns ``None`` if not found.
493        """
494        return await self._http.get(
495            f"squid-api/v1/ai/knowledge-base/getContext/{self._kb_id}/{context_id}"
496        )
497
498    async def list_contexts(self) -> list[dict]:
499        """List all contexts in the knowledge base.
500
501        Deprecated: fetches every context in one call with no pagination — expensive for large
502        knowledge bases. Use :meth:`list_contexts_page` instead, which supports
503        ``offset``/``limit``/``search``.
504
505        Returns:
506            A list of ``AiKnowledgeBaseContext`` dicts.
507        """
508        result = await self._http.get(f"squid-api/v1/ai/knowledge-base/listContexts/{self._kb_id}")
509        return result.get("contexts", []) if result else []
510
511    async def list_contexts_page(
512        self,
513        *,
514        offset: int | None = None,
515        limit: int | None = None,
516        search: str | None = None,
517    ) -> dict:
518        """List a page of contexts in the knowledge base.
519
520        Args:
521            offset: The number of contexts to skip, for pagination.
522            limit: The maximum number of contexts to return, for pagination.
523            search: Case-insensitive substring search across id/title only.
524
525        Returns:
526            A dict with ``contexts`` (a list of ``AiKnowledgeBaseContext`` dicts for the
527            requested page) and ``totalCount`` (the total number of contexts in the
528            knowledge base, ignoring ``offset``/``limit``).
529        """
530        params = {
531            key: str(value)
532            for key, value in {"offset": offset, "limit": limit, "search": search}.items()
533            if value is not None
534        }
535        result = await self._http.get(
536            f"squid-api/v1/ai/knowledge-base/listContextsPage/{self._kb_id}",
537            params=params or None,
538        )
539        return result if result else {"contexts": [], "totalCount": 0}
540
541    async def upsert_contexts(
542        self,
543        contexts: list[ContextRequest],
544        files: list[tuple[str, bytes, str]] | None = None,
545    ) -> dict:
546        """Add or update contexts in the knowledge base.
547
548        Args:
549            contexts: A list of context request objects. Each must be either:
550                - A :class:`TextContextRequest`: ``{'contextId', 'type': 'text', 'title', 'text', ...}``
551                - A :class:`FileContextRequest`: ``{'contextId', 'type': 'file', ...}``
552            files: For file contexts, provide the actual file data as a list of
553                ``(filename, data_bytes, content_type)`` tuples. Must match the
554                order of file contexts in the ``contexts`` list.
555
556        Returns:
557            A dict with ``failures``: a list of ``UpsertContextStatusError`` dicts
558            for any contexts that failed to upsert.
559
560        Example::
561
562            await kb.upsert_contexts(
563                [
564                    {"contextId": "doc-1", "type": "text", "title": "FAQ", "text": "..."},
565                    {"contextId": "doc-2", "type": "file"},
566                ],
567                files=[
568                    ("manual.pdf", pdf_bytes, "application/pdf"),
569                ],
570            )
571        """
572        form_data = {
573            "knowledgeBaseId": self._kb_id,
574            "contexts": json.dumps(contexts),
575        }
576        file_tuples: list[tuple[str, tuple[str, bytes, str]]] = []
577        if files:
578            for fname, fdata, ftype in files:
579                file_tuples.append(("files", (fname, fdata, ftype)))
580        return await self._http.post_form(
581            "squid-api/v1/ai/knowledge-base/upsertContexts",
582            data=form_data,
583            files=file_tuples,
584        )
585
586    async def delete_contexts(self, context_ids: list[str]) -> None:
587        """Delete contexts by their IDs.
588
589        Args:
590            context_ids: List of context IDs to delete.
591        """
592        await self._http.post(
593            "squid-api/v1/ai/knowledge-base/deleteContexts",
594            {"knowledgeBaseId": self._kb_id, "contextIds": context_ids},
595        )
596
597    # --- Search ---
598
599    async def search(
600        self,
601        prompt: str,
602        options: KnowledgeBaseSearchOptions | None = None,
603    ) -> list[dict]:
604        """Search the knowledge base using semantic search.
605
606        Args:
607            prompt: The search query in natural language.
608            options: Search options. See :class:`KnowledgeBaseSearchOptions`.
609                Supports: ``limit``, ``chunkLimit``, ``rerankProvider``, ``chatModel``.
610
611        Returns:
612            A list of ``AiKnowledgeBaseSearchResultChunk`` dicts, each with:
613            ``contextId``, ``data``, ``metadata``, ``score``.
614
615        Example::
616
617            chunks = await kb.search(
618                "How do I reset my password?",
619                options={
620                    "limit": 5,
621                    "chatModel": "gemini-3-flash",
622                },
623            )
624            for chunk in chunks:
625                print(f"Score: {chunk['score']}, Data: {chunk['data'][:100]}")
626        """
627        search_options: dict[str, Any] = {"prompt": prompt, **(options or {})}
628        result = await self._http.post(
629            "squid-api/v1/ai/knowledge-base/search",
630            {
631                "knowledgeBaseId": self._kb_id,
632                "prompt": prompt,
633                "options": search_options,
634            },
635        )
636        return result.get("chunks", []) if result else []

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?")
KnowledgeBaseClient(http: squidcloud.http.HttpTransport, kb_id: str)
430    def __init__(self, http: HttpTransport, kb_id: str) -> None:
431        self._http = http
432        self._kb_id = kb_id
async def get(self) -> dict | None:
434    async def get(self) -> dict | None:
435        """Get the knowledge base details.
436
437        Returns:
438            An ``AiKnowledgeBase`` dict with keys: ``id``, ``appId``,
439            ``description``, ``metadataFields``, ``embeddingModel``,
440            ``chatModel``, ``updatedAt``. Returns ``None`` if not found.
441        """
442        return await self._http.get(f"squid-api/v1/ai/knowledge-base/get/{self._kb_id}")

Get the knowledge base details.

Returns:

An AiKnowledgeBase dict with keys: id, appId, description, metadataFields, embeddingModel, chatModel, updatedAt. Returns None if not found.

async def upsert( self, *, description: str | None = None, metadata_fields: list[AiKnowledgeBaseMetadataField] | None = None, embedding_model: str | None = None, chat_model: str | IntegrationModelSpec | None = None, name: str | None = None) -> None:
444    async def upsert(
445        self,
446        *,
447        description: str | None = None,
448        metadata_fields: list[AiKnowledgeBaseMetadataField] | None = None,
449        embedding_model: str | None = None,
450        chat_model: AiChatModelSelection | None = None,
451        name: str | None = None,
452    ) -> None:
453        """Create or update the knowledge base.
454
455        Args:
456            description: Description of the knowledge base's content.
457            metadata_fields: Schema for metadata fields used in filtering.
458                Each field: ``{'name': str, 'dataType': str, 'required': bool, 'description'?: str}``.
459            embedding_model: The embedding model name for vectorization.
460            chat_model: The LLM model for answering questions over this KB.
461            name: Display name for the knowledge base.
462        """
463        kb: dict[str, Any] = {"id": self._kb_id}
464        if description is not None:
465            kb["description"] = description
466        if metadata_fields is not None:
467            kb["metadataFields"] = metadata_fields
468        if embedding_model is not None:
469            kb["embeddingModel"] = embedding_model
470        if chat_model is not None:
471            kb["chatModel"] = chat_model
472        if name is not None:
473            kb["name"] = name
474        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.
  • chat_model: The LLM model for answering questions over this KB.
  • name: Display name for the knowledge base.
async def delete(self) -> None:
476    async def delete(self) -> None:
477        """Delete the knowledge base and all its contexts permanently."""
478        await self._http.post("squid-api/v1/ai/knowledge-base/delete", {"id": self._kb_id})

Delete the knowledge base and all its contexts permanently.

async def get_context(self, context_id: str) -> dict | None:
482    async def get_context(self, context_id: str) -> dict | None:
483        """Get a specific context entry.
484
485        Args:
486            context_id: The unique context identifier.
487
488        Returns:
489            An ``AiKnowledgeBaseContext`` dict with keys: ``id``, ``appId``,
490            ``knowledgeBaseId``, ``createdAt``, ``updatedAt``, ``type``,
491            ``title``, ``text``, ``preview``, ``sizeBytes``, ``metadata``,
492            ``requestConfig``. Returns ``None`` if not found.
493        """
494        return await self._http.get(
495            f"squid-api/v1/ai/knowledge-base/getContext/{self._kb_id}/{context_id}"
496        )

Get a specific context entry.

Arguments:
  • context_id: The unique context identifier.
Returns:

An AiKnowledgeBaseContext dict with keys: id, appId, knowledgeBaseId, createdAt, updatedAt, type, title, text, preview, sizeBytes, metadata, requestConfig. Returns None if not found.

async def list_contexts(self) -> list[dict]:
498    async def list_contexts(self) -> list[dict]:
499        """List all contexts in the knowledge base.
500
501        Deprecated: fetches every context in one call with no pagination — expensive for large
502        knowledge bases. Use :meth:`list_contexts_page` instead, which supports
503        ``offset``/``limit``/``search``.
504
505        Returns:
506            A list of ``AiKnowledgeBaseContext`` dicts.
507        """
508        result = await self._http.get(f"squid-api/v1/ai/knowledge-base/listContexts/{self._kb_id}")
509        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 AiKnowledgeBaseContext dicts.

async def list_contexts_page( self, *, offset: int | None = None, limit: int | None = None, search: str | None = None) -> dict:
511    async def list_contexts_page(
512        self,
513        *,
514        offset: int | None = None,
515        limit: int | None = None,
516        search: str | None = None,
517    ) -> dict:
518        """List a page of contexts in the knowledge base.
519
520        Args:
521            offset: The number of contexts to skip, for pagination.
522            limit: The maximum number of contexts to return, for pagination.
523            search: Case-insensitive substring search across id/title only.
524
525        Returns:
526            A dict with ``contexts`` (a list of ``AiKnowledgeBaseContext`` dicts for the
527            requested page) and ``totalCount`` (the total number of contexts in the
528            knowledge base, ignoring ``offset``/``limit``).
529        """
530        params = {
531            key: str(value)
532            for key, value in {"offset": offset, "limit": limit, "search": search}.items()
533            if value is not None
534        }
535        result = await self._http.get(
536            f"squid-api/v1/ai/knowledge-base/listContextsPage/{self._kb_id}",
537            params=params or None,
538        )
539        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 of AiKnowledgeBaseContext dicts for the requested page) and totalCount (the total number of contexts in the knowledge base, ignoring offset/limit).

async def upsert_contexts( self, contexts: list[TextContextRequest | FileContextRequest], files: list[tuple[str, bytes, str]] | None = None) -> dict:
541    async def upsert_contexts(
542        self,
543        contexts: list[ContextRequest],
544        files: list[tuple[str, bytes, str]] | None = None,
545    ) -> dict:
546        """Add or update contexts in the knowledge base.
547
548        Args:
549            contexts: A list of context request objects. Each must be either:
550                - A :class:`TextContextRequest`: ``{'contextId', 'type': 'text', 'title', 'text', ...}``
551                - A :class:`FileContextRequest`: ``{'contextId', 'type': 'file', ...}``
552            files: For file contexts, provide the actual file data as a list of
553                ``(filename, data_bytes, content_type)`` tuples. Must match the
554                order of file contexts in the ``contexts`` list.
555
556        Returns:
557            A dict with ``failures``: a list of ``UpsertContextStatusError`` dicts
558            for any contexts that failed to upsert.
559
560        Example::
561
562            await kb.upsert_contexts(
563                [
564                    {"contextId": "doc-1", "type": "text", "title": "FAQ", "text": "..."},
565                    {"contextId": "doc-2", "type": "file"},
566                ],
567                files=[
568                    ("manual.pdf", pdf_bytes, "application/pdf"),
569                ],
570            )
571        """
572        form_data = {
573            "knowledgeBaseId": self._kb_id,
574            "contexts": json.dumps(contexts),
575        }
576        file_tuples: list[tuple[str, tuple[str, bytes, str]]] = []
577        if files:
578            for fname, fdata, ftype in files:
579                file_tuples.append(("files", (fname, fdata, ftype)))
580        return await self._http.post_form(
581            "squid-api/v1/ai/knowledge-base/upsertContexts",
582            data=form_data,
583            files=file_tuples,
584        )

Add or update contexts in the knowledge base.

Arguments:
  • contexts: A list of context request objects. Each must be either:
  • 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 the contexts list.
Returns:

A dict with failures: a list of UpsertContextStatusError dicts 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"),
    ],
)
async def delete_contexts(self, context_ids: list[str]) -> None:
586    async def delete_contexts(self, context_ids: list[str]) -> None:
587        """Delete contexts by their IDs.
588
589        Args:
590            context_ids: List of context IDs to delete.
591        """
592        await self._http.post(
593            "squid-api/v1/ai/knowledge-base/deleteContexts",
594            {"knowledgeBaseId": self._kb_id, "contextIds": context_ids},
595        )

Delete contexts by their IDs.

Arguments:
  • context_ids: List of context IDs to delete.
async def search( self, prompt: str, options: KnowledgeBaseSearchOptions | None = None) -> list[dict]:
599    async def search(
600        self,
601        prompt: str,
602        options: KnowledgeBaseSearchOptions | None = None,
603    ) -> list[dict]:
604        """Search the knowledge base using semantic search.
605
606        Args:
607            prompt: The search query in natural language.
608            options: Search options. See :class:`KnowledgeBaseSearchOptions`.
609                Supports: ``limit``, ``chunkLimit``, ``rerankProvider``, ``chatModel``.
610
611        Returns:
612            A list of ``AiKnowledgeBaseSearchResultChunk`` dicts, each with:
613            ``contextId``, ``data``, ``metadata``, ``score``.
614
615        Example::
616
617            chunks = await kb.search(
618                "How do I reset my password?",
619                options={
620                    "limit": 5,
621                    "chatModel": "gemini-3-flash",
622                },
623            )
624            for chunk in chunks:
625                print(f"Score: {chunk['score']}, Data: {chunk['data'][:100]}")
626        """
627        search_options: dict[str, Any] = {"prompt": prompt, **(options or {})}
628        result = await self._http.post(
629            "squid-api/v1/ai/knowledge-base/search",
630            {
631                "knowledgeBaseId": self._kb_id,
632                "prompt": prompt,
633                "options": search_options,
634            },
635        )
636        return result.get("chunks", []) if result else []

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.
Returns:

A list of AiKnowledgeBaseSearchResultChunk dicts, 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]}")
class KnowledgeBaseSearchOptions(typing.TypedDict):
474class KnowledgeBaseSearchOptions(TypedDict, total=False):
475    """Options for knowledge base search."""
476
477    prompt: str
478    """The search prompt."""
479    limit: int
480    """Max number of results to return."""
481    chunkLimit: int
482    """How many chunks to search over (default 100)."""
483    rerankProvider: AiRerankProvider
484    """Reranker provider (default 'cohere')."""
485    chatModel: AiChatModelSelection
486    """Model to use for answering."""
487    searchMode: Literal["vector", "hybrid", "keyword"]
488    """Retrieval mode: 'hybrid' (default; BM25+dense fusion where supported), 'vector' (dense only), or
489    'keyword' (pure lexical — every whitespace-separated term must appear as a literal, case-insensitive
490    substring)."""

Options for knowledge base search.

prompt: str

The search prompt.

limit: int

Max number of results to return.

chunkLimit: int

How many chunks to search over (default 100).

rerankProvider: Literal['cohere']

Reranker provider (default 'cohere').

chatModel: str | IntegrationModelSpec

Model to use for answering.

searchMode: Literal['vector', 'hybrid', 'keyword']

Retrieval mode: 'hybrid' (default; BM25+dense fusion where supported), 'vector' (dense only), or 'keyword' (pure lexical — every whitespace-separated term must appear as a literal, case-insensitive substring).

class MatchmakingClient:
 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.

MatchmakingClient(http: squidcloud.http.HttpTransport)
24    def __init__(self, http: HttpTransport) -> None:
25        self._http = http
async def create_match_maker( self, match_maker_id: str, description: str, categories: list[MmCategory]) -> dict:
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.

async def get_match_maker(self, match_maker_id: str) -> dict | None:
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.

async def list_match_makers(self) -> list[dict]:
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.

async def delete_match_maker(self, match_maker_id: str) -> None:
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.

async def insert_entities( self, match_maker_id: str, entities: list[MmEntity]) -> None:
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.

async def delete_entity(self, match_maker_id: str, entity_id: str) -> None:
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.

async def get_entity(self, match_maker_id: str, entity_id: str) -> dict | None:
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.

async def list_entities( self, match_maker_id: str, category_id: str, options: MmListEntitiesOptions | None = None) -> list[dict]:
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.

async def find_matches( self, match_maker_id: str, entity_id: str, options: MmFindMatchesOptions | None = None) -> list[dict]:
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.

async def find_matches_for_entity( self, match_maker_id: str, entity: MmEntity, options: MmFindMatchesOptions | None = None) -> list[dict]:
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).

class MmCategory(typing.TypedDict):
596class MmCategory(TypedDict):
597    """Matchmaking category."""
598
599    id: str
600    description: str

Matchmaking category.

id: str
description: str
class MmEntity(typing.TypedDict):
603class MmEntity(TypedDict, total=False):
604    """Matchmaking entity."""
605
606    id: str
607    content: str
608    categoryId: str
609    metadata: dict[str, Any]

Matchmaking entity.

id: str
content: str
categoryId: str
metadata: dict[str, typing.Any]
class MmFindMatchesOptions(typing.TypedDict):
612class MmFindMatchesOptions(TypedDict, total=False):
613    """Options for finding matches."""
614
615    metadataFilter: dict[str, Any]
616    """AiContextMetadataFilter conditions."""
617    limit: int
618    """Max matches to return (default 100, max 100)."""
619    matchToCategoryId: str
620    """Category to match against."""

Options for finding matches.

metadataFilter: dict[str, typing.Any]

AiContextMetadataFilter conditions.

limit: int

Max matches to return (default 100, max 100).

matchToCategoryId: str

Category to match against.

class MmListEntitiesOptions(typing.TypedDict):
623class MmListEntitiesOptions(TypedDict, total=False):
624    """Options for listing entities."""
625
626    metadataFilter: dict[str, Any]
627    limit: int

Options for listing entities.

metadataFilter: dict[str, typing.Any]
limit: int
class ModelIdSpec(typing.TypedDict):
44class ModelIdSpec(TypedDict, total=False):
45    """An AI chat model available to the app.
46
47    Returned by :meth:`AiClient.list_chat_models`.
48    """
49
50    modelId: AiChatModelName
51    """The model ID used for API calls. Required."""
52    integrationId: str
53    """The integration ID if this model comes from an integration (OpenAI-compatible,
54    Bedrock). Absent for Squid-provided models."""
55    displayName: str
56    """Human-readable display name for the model (e.g. 'GPT-4o')."""
57    description: str
58    """Short human-readable description of the model. Absent for custom integration models."""
59    replacedBy: AiChatModelName
60    """Set only for deprecated models: the active model that calls to this model are
61    routed to. Absent for active models."""
62    source: AiModelSource
63    """Where the model comes from: 'vendor' (Squid-provided), 'connector' (provided by an
64    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().

modelId: str

The model ID used for API calls. Required.

integrationId: str

The integration ID if this model comes from an integration (OpenAI-compatible, Bedrock). Absent for Squid-provided models.

displayName: str

Human-readable display name for the model (e.g. 'GPT-4o').

description: str

Short human-readable description of the model. Absent for custom integration models.

replacedBy: str

Set only for deprecated models: the active model that calls to this model are routed to. Absent for active models.

source: Literal['vendor', 'connector', 'custom']

Where the model comes from: 'vendor' (Squid-provided), 'connector' (provided by an integration configured on the app), or 'custom' (user-added model from the app's bundle).

class Squid:
 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!")
Squid( app_id: str, region: str, api_key: str | None = None, environment_id: str | None = None, squid_developer_id: str | None = None)
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}'.
app_id: str
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).

region: str
100    @property
101    def region(self) -> str:
102        """The deployment region."""
103        return self._region

The deployment region.

client_id: str
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).

def ai(self) -> AiClient:
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 AiClient instance.

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")
def web(self) -> WebClient:
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 WebClient instance.

Example::

content = await squid.web().get_url_content("https://example.com")
results = await squid.web().ai_search("latest AI news")
def matchmaking(self) -> MatchmakingClient:
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 MatchmakingClient instance.

Example::

mm = squid.matchmaking()
await mm.create_match_maker("jobs", "Job matching", categories=[...])
matches = await mm.find_matches("jobs", "entity-1")
def extraction(self) -> ExtractionClient:
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 ExtractionClient instance.

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"
)
async def execute_function(self, function_name: str, *params: Any) -> Any:
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)
async def execute_webhook( self, webhook_id: str, *, body: Any = None, headers: dict[str, str] | None = None, method: str = 'POST') -> Any:
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"})
def get_webhook_url(self, webhook_id: str) -> str:
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"
async def execute_ai_query( self, integration_id: str, prompt: str, *, options: AiQueryOptions | None = None, response_format: dict[str, Any] | None = None) -> dict:
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 AiQueryOptions controlling collection selection, query generation (including allowClarification), result analysis (including enableCodeInterpreter), memory, AI validation, per-stage model overrides via aiOptions, and custom instructions.
  • response_format: Optional structured output format, e.g., {"type": "json_schema", "schema": {...}}.
Returns:

An AiQueryResponse dict 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"])
async def close(self) -> None:
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.

class SquidHttpError(builtins.Exception):
 89class SquidHttpError(Exception):
 90    """Raised when the Squid API returns an HTTP error response (status >= 400).
 91
 92    Attributes:
 93        status_code: The HTTP status code.
 94        url: The URL that was requested.
 95        body: The parsed response body, if available.
 96    """
 97
 98    def __init__(self, status_code: int, message: str, url: str, body: Any = None):
 99        self.status_code = status_code
100        self.url = url
101        self.body = body
102        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.
SquidHttpError(status_code: int, message: str, url: str, body: Any = None)
 98    def __init__(self, status_code: int, message: str, url: str, body: Any = None):
 99        self.status_code = status_code
100        self.url = url
101        self.body = body
102        super().__init__(f"HTTP {status_code}: {message} (url={url})")
status_code
url
body
class StableDiffusionOptions(typing.TypedDict):
579class StableDiffusionOptions(TypedDict, total=False):
580    """Options for Stable Diffusion Core image generation."""
581
582    modelName: Literal["stable-diffusion-core"]
583    aspectRatio: Literal["16:9", "1:1", "21:9", "2:3", "3:2", "4:5", "5:4", "9:16", "9:21"]
584    negativePrompt: str
585    seed: int
586    stylePreset: str
587    outputFormat: str

Options for Stable Diffusion Core image generation.

modelName: Literal['stable-diffusion-core']
aspectRatio: Literal['16:9', '1:1', '21:9', '2:3', '3:2', '4:5', '5:4', '9:16', '9:21']
negativePrompt: str
seed: int
stylePreset: str
outputFormat: str
class TextContextRequest(typing.TypedDict):
439class TextContextRequest(TypedDict, total=False):
440    """Request to upsert a text context."""
441
442    contextId: str
443    type: Literal["text"]
444    title: str
445    text: str
446    metadata: dict[str, Any]
447    options: AiContextTextOptions

Request to upsert a text context.

contextId: str
type: Literal['text']
title: str
text: str
metadata: dict[str, typing.Any]
class UpsertAgentOptions(typing.TypedDict):
339class UpsertAgentOptions(TypedDict, total=False):
340    """Options for creating/updating an agent."""
341
342    description: str
343    """Description of the agent's purpose."""
344    isPublic: bool
345    """Whether the agent is publicly accessible."""
346    auditLog: bool
347    """Enable audit logging."""
348    apiKey: str
349    """API key for this agent."""
350    options: AiChatOptions
351    """Default chat options."""

Options for creating/updating an agent.

description: str

Description of the agent's purpose.

isPublic: bool

Whether the agent is publicly accessible.

auditLog: bool

Enable audit logging.

apiKey: str

API key for this agent.

options: AiChatOptions

Default chat options.

class WebAiSearchResponse(typing.TypedDict):
697class WebAiSearchResponse(TypedDict):
698    """Response from AI web search."""
699
700    markdownText: str
701    citedUrls: list[dict[str, str]]

Response from AI web search.

markdownText: str
citedUrls: list[dict[str, str]]
class WebClient:
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.

WebClient(http: squidcloud.http.HttpTransport)
19    def __init__(self, http: HttpTransport) -> None:
20        self._http = http
async def get_url_content(self, url: str) -> str:
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.

async def create_short_url( self, url: str, *, seconds_to_live: int | None = None, file_extension: str | None = None) -> WebShortUrlResponse:
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'.

async def create_short_urls( self, urls: list[str], *, seconds_to_live: int | None = None, file_extension: str | None = None) -> WebShortUrlBulkResponse:
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'.

async def delete_short_url(self, url_id: str) -> None:
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})

Delete a short URL.

async def delete_short_urls(self, url_ids: list[str]) -> None:
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})

Delete multiple short URLs.

class WebShortUrlBulkResponse(typing.TypedDict):
689class WebShortUrlBulkResponse(TypedDict):
690    """Response from creating bulk short URLs."""
691
692    ids: list[str]
693    shortUrls: list[str]
694    expiry: str

Response from creating bulk short URLs.

ids: list[str]
shortUrls: list[str]
expiry: str
class WebShortUrlResponse(typing.TypedDict):
681class WebShortUrlResponse(TypedDict):
682    """Response from creating a short URL."""
683
684    id: str
685    shortUrl: str
686    expiry: str

Response from creating a short URL.

id: str
shortUrl: str
expiry: str