Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/gooddata-sdk/src/gooddata_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@
CatalogSectionSlideTemplate,
)
from gooddata_sdk.catalog.organization.common.widget_slides_template import CatalogWidgetSlidesTemplate
from gooddata_sdk.catalog.organization.entity_model.agent import (
CatalogAgent,
CatalogAgentAttributes,
CatalogAgentDocument,
CatalogAgentPatchDocument,
)
from gooddata_sdk.catalog.organization.entity_model.directive import CatalogCspDirective
from gooddata_sdk.catalog.organization.entity_model.export_template import (
CatalogExportTemplate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from pathlib import Path

from gooddata_api_client import apis
from gooddata_api_client.api.ai_agents_api import AIAgentsApi
from gooddata_api_client.model.json_api_organization_out_document import JsonApiOrganizationOutDocument

from gooddata_sdk.catalog.organization.entity_model.organization import CatalogOrganization
Expand All @@ -19,6 +20,7 @@ def __init__(self, api_client: GoodDataApiClient) -> None:
self._layout_api: apis.LayoutApi = api_client.layout_api
self._actions_api: apis.ActionsApi = api_client.actions_api
self._user_management_api: apis.UserManagementApi = api_client.user_management_api
self._ai_agents_api: AIAgentsApi = api_client.ai_agents_api

def get_organization(self) -> CatalogOrganization:
# The generated client does work properly with redirecting APIs
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# (C) 2026 GoodData Corporation
from __future__ import annotations

from typing import Any

import attrs
from gooddata_api_client.model.json_api_agent_in import JsonApiAgentIn
from gooddata_api_client.model.json_api_agent_in_attributes import JsonApiAgentInAttributes
from gooddata_api_client.model.json_api_agent_in_document import JsonApiAgentInDocument
from gooddata_api_client.model.json_api_agent_patch_document import JsonApiAgentPatchDocument

from gooddata_sdk.catalog.base import Base
from gooddata_sdk.utils import safeget


@attrs.define(kw_only=True)
class CatalogAgentAttributes(Base):
"""Attributes of an AI agent entity."""

title: str | None = None
description: str | None = None
ai_knowledge: bool | None = None
available_to_all: bool | None = None
custom_skills: list[str] | None = None
enabled: bool | None = None
personality: str | None = None
skills_mode: str | None = None

@staticmethod
def client_class() -> type[JsonApiAgentInAttributes]:
return JsonApiAgentInAttributes


@attrs.define(kw_only=True)
class CatalogAgent(Base):
"""Represents an AI agent entity with its configuration."""

id: str
attributes: CatalogAgentAttributes | None = None

@staticmethod
def client_class() -> type[JsonApiAgentIn]:
return JsonApiAgentIn

@classmethod
def init(
cls,
id: str,
title: str | None = None,
description: str | None = None,
ai_knowledge: bool | None = None,
available_to_all: bool | None = None,
custom_skills: list[str] | None = None,
enabled: bool | None = None,
personality: str | None = None,
skills_mode: str | None = None,
) -> CatalogAgent:
"""Convenience factory for building a CatalogAgent."""
return cls(
id=id,
attributes=CatalogAgentAttributes(
title=title,
description=description,
ai_knowledge=ai_knowledge,
available_to_all=available_to_all,
custom_skills=custom_skills,
enabled=enabled,
personality=personality,
skills_mode=skills_mode,
),
)

@classmethod
def from_api(cls, entity: dict[str, Any]) -> CatalogAgent:
ea = entity.get("attributes") or {}
return cls(
id=entity["id"],
attributes=CatalogAgentAttributes(
title=safeget(ea, ["title"]),
description=safeget(ea, ["description"]),
ai_knowledge=safeget(ea, ["ai_knowledge"]),
available_to_all=safeget(ea, ["available_to_all"]),
custom_skills=safeget(ea, ["custom_skills"]),
enabled=safeget(ea, ["enabled"]),
personality=safeget(ea, ["personality"]),
skills_mode=safeget(ea, ["skills_mode"]),
),
)


@attrs.define(kw_only=True)
class CatalogAgentDocument(Base):
"""Wraps CatalogAgent for POST (create) requests."""

data: CatalogAgent

@staticmethod
def client_class() -> type[JsonApiAgentInDocument]:
return JsonApiAgentInDocument


@attrs.define(kw_only=True)
class CatalogAgentPatchDocument(Base):
"""Wraps CatalogAgent for PATCH requests."""

data: CatalogAgent

@staticmethod
def client_class() -> type[JsonApiAgentPatchDocument]:
return JsonApiAgentPatchDocument
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@

from gooddata_sdk import CatalogDeclarativeExportTemplate, CatalogExportTemplate
from gooddata_sdk.catalog.catalog_service_base import CatalogServiceBase
from gooddata_sdk.catalog.organization.entity_model.agent import (
CatalogAgent,
CatalogAgentDocument,
CatalogAgentPatchDocument,
)
from gooddata_sdk.catalog.organization.entity_model.directive import CatalogCspDirective
from gooddata_sdk.catalog.organization.entity_model.identity_provider import CatalogIdentityProvider
from gooddata_sdk.catalog.organization.entity_model.jwk import CatalogJwk, CatalogJwkDocument
Expand Down Expand Up @@ -584,6 +589,103 @@ def delete_llm_provider(self, id: str) -> None:
"""
self._entities_api.delete_entity_llm_providers(id, _check_return_type=False)

# Agent APIs

def get_agent(self, id: str) -> CatalogAgent:
"""Get an AI agent by ID.

Args:
id: Agent identifier

Returns:
CatalogAgent: Retrieved agent
"""
response = self._ai_agents_api.get_entity_agents(id, _check_return_type=False)
return CatalogAgent.from_api(response.data)

def list_agents(
self,
filter: str | None = None,
page: int | None = None,
size: int | None = None,
sort: list[str] | None = None,
) -> list[CatalogAgent]:
"""List all AI agents.

Args:
filter: Optional filter string
page: Zero-based page index (0..N)
size: The size of the page to be returned
sort: Sorting criteria in the format: property,(asc|desc).

Returns:
list[CatalogAgent]: List of agents
"""
kwargs: dict[str, Any] = {}
if filter is not None:
kwargs["filter"] = filter
if page is not None:
kwargs["page"] = page
if size is not None:
kwargs["size"] = size
if sort is not None:
kwargs["sort"] = sort
kwargs["_check_return_type"] = False

response = self._ai_agents_api.get_all_entities_agents(**kwargs)
return [CatalogAgent.from_api(agent) for agent in response.data]

def create_agent(self, agent: CatalogAgent) -> CatalogAgent:
"""Create a new AI agent.

Args:
agent: Agent object to create

Returns:
CatalogAgent: Created agent
"""
agent_document = CatalogAgentDocument(data=agent)
response = self._ai_agents_api.create_entity_agents(
json_api_agent_in_document=agent_document.to_api(), _check_return_type=False
)
return CatalogAgent.from_api(response.data)

def update_agent(self, agent: CatalogAgent) -> CatalogAgent:
"""Update an existing AI agent using PUT semantics.

Args:
agent: Agent object with updated values

Returns:
CatalogAgent: Updated agent
"""
agent_document = CatalogAgentDocument(data=agent)
response = self._ai_agents_api.update_entity_agents(agent.id, agent_document.to_api(), _check_return_type=False)
return CatalogAgent.from_api(response.data)

def patch_agent(self, agent: CatalogAgent) -> CatalogAgent:
"""Patch an existing AI agent using PATCH semantics.

Args:
agent: Agent object with fields to patch

Returns:
CatalogAgent: Updated agent
"""
agent_patch_document = CatalogAgentPatchDocument(data=agent)
response = self._ai_agents_api.patch_entity_agents(
agent.id, agent_patch_document.to_api(), _check_return_type=False
)
return CatalogAgent.from_api(response.data)

def delete_agent(self, id: str) -> None:
"""Delete an AI agent.

Args:
id: Agent identifier
"""
self._ai_agents_api.delete_entity_agents(id, _check_return_type=False)

# Layout APIs

def get_declarative_notification_channels(self) -> list[CatalogDeclarativeNotificationChannel]:
Expand Down
6 changes: 6 additions & 0 deletions packages/gooddata-sdk/src/gooddata_sdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import gooddata_api_client as api_client
import requests
from gooddata_api_client import apis
from gooddata_api_client.api.ai_agents_api import AIAgentsApi

from gooddata_sdk import __version__
from gooddata_sdk.utils import HttpMethod
Expand Down Expand Up @@ -71,6 +72,7 @@ def __init__(
self._actions_api = apis.ActionsApi(self._api_client)
self._user_management_api = apis.UserManagementApi(self._api_client)
self._appearance_api = apis.AppearanceApi(self._api_client)
self._ai_agents_api = AIAgentsApi(self._api_client)
self._executions_cancellable = executions_cancellable

def _do_post_request(
Expand Down Expand Up @@ -158,6 +160,10 @@ def user_management_api(self) -> apis.UserManagementApi:
def appearance_api(self) -> apis.AppearanceApi:
return self._appearance_api

@property
def ai_agents_api(self) -> AIAgentsApi:
return self._ai_agents_api

@property
def executions_cancellable(self) -> bool:
return self._executions_cancellable
Loading
Loading