Skip to content

Commit 3bdbdf6

Browse files
committed
feat(gooddata-sdk): [AUTO] Add JsonApiAgent CRUD entity and DeclarativeAgent/DeclarativeAgents models
1 parent 4cb8139 commit 3bdbdf6

6 files changed

Lines changed: 434 additions & 0 deletions

File tree

packages/gooddata-sdk/src/gooddata_sdk/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@
9999
CatalogSectionSlideTemplate,
100100
)
101101
from gooddata_sdk.catalog.organization.common.widget_slides_template import CatalogWidgetSlidesTemplate
102+
from gooddata_sdk.catalog.organization.entity_model.agent import (
103+
CatalogAgent,
104+
CatalogAgentAttributes,
105+
CatalogAgentDocument,
106+
CatalogAgentPatchDocument,
107+
)
102108
from gooddata_sdk.catalog.organization.entity_model.directive import CatalogCspDirective
103109
from gooddata_sdk.catalog.organization.entity_model.export_template import (
104110
CatalogExportTemplate,

packages/gooddata-sdk/src/gooddata_sdk/catalog/catalog_service_base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from pathlib import Path
55

66
from gooddata_api_client import apis
7+
from gooddata_api_client.api.ai_agents_api import AIAgentsApi
78
from gooddata_api_client.model.json_api_organization_out_document import JsonApiOrganizationOutDocument
89

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

2325
def get_organization(self) -> CatalogOrganization:
2426
# The generated client does work properly with redirecting APIs
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# (C) 2026 GoodData Corporation
2+
from __future__ import annotations
3+
4+
from typing import Any
5+
6+
import attrs
7+
from gooddata_api_client.model.json_api_agent_in import JsonApiAgentIn
8+
from gooddata_api_client.model.json_api_agent_in_attributes import JsonApiAgentInAttributes
9+
from gooddata_api_client.model.json_api_agent_in_document import JsonApiAgentInDocument
10+
from gooddata_api_client.model.json_api_agent_patch_document import JsonApiAgentPatchDocument
11+
12+
from gooddata_sdk.catalog.base import Base
13+
from gooddata_sdk.utils import safeget
14+
15+
16+
@attrs.define(kw_only=True)
17+
class CatalogAgentAttributes(Base):
18+
"""Attributes of an AI agent entity."""
19+
20+
title: str | None = None
21+
description: str | None = None
22+
ai_knowledge: bool | None = None
23+
available_to_all: bool | None = None
24+
custom_skills: list[str] | None = None
25+
enabled: bool | None = None
26+
personality: str | None = None
27+
skills_mode: str | None = None
28+
29+
@staticmethod
30+
def client_class() -> type[JsonApiAgentInAttributes]:
31+
return JsonApiAgentInAttributes
32+
33+
34+
@attrs.define(kw_only=True)
35+
class CatalogAgent(Base):
36+
"""Represents an AI agent entity with its configuration."""
37+
38+
id: str
39+
attributes: CatalogAgentAttributes | None = None
40+
41+
@staticmethod
42+
def client_class() -> type[JsonApiAgentIn]:
43+
return JsonApiAgentIn
44+
45+
@classmethod
46+
def init(
47+
cls,
48+
id: str,
49+
title: str | None = None,
50+
description: str | None = None,
51+
ai_knowledge: bool | None = None,
52+
available_to_all: bool | None = None,
53+
custom_skills: list[str] | None = None,
54+
enabled: bool | None = None,
55+
personality: str | None = None,
56+
skills_mode: str | None = None,
57+
) -> CatalogAgent:
58+
"""Convenience factory for building a CatalogAgent."""
59+
return cls(
60+
id=id,
61+
attributes=CatalogAgentAttributes(
62+
title=title,
63+
description=description,
64+
ai_knowledge=ai_knowledge,
65+
available_to_all=available_to_all,
66+
custom_skills=custom_skills,
67+
enabled=enabled,
68+
personality=personality,
69+
skills_mode=skills_mode,
70+
),
71+
)
72+
73+
@classmethod
74+
def from_api(cls, entity: dict[str, Any]) -> CatalogAgent:
75+
ea = entity.get("attributes") or {}
76+
return cls(
77+
id=entity["id"],
78+
attributes=CatalogAgentAttributes(
79+
title=safeget(ea, ["title"]),
80+
description=safeget(ea, ["description"]),
81+
ai_knowledge=safeget(ea, ["ai_knowledge"]),
82+
available_to_all=safeget(ea, ["available_to_all"]),
83+
custom_skills=safeget(ea, ["custom_skills"]),
84+
enabled=safeget(ea, ["enabled"]),
85+
personality=safeget(ea, ["personality"]),
86+
skills_mode=safeget(ea, ["skills_mode"]),
87+
),
88+
)
89+
90+
91+
@attrs.define(kw_only=True)
92+
class CatalogAgentDocument(Base):
93+
"""Wraps CatalogAgent for POST (create) requests."""
94+
95+
data: CatalogAgent
96+
97+
@staticmethod
98+
def client_class() -> type[JsonApiAgentInDocument]:
99+
return JsonApiAgentInDocument
100+
101+
102+
@attrs.define(kw_only=True)
103+
class CatalogAgentPatchDocument(Base):
104+
"""Wraps CatalogAgent for PATCH requests."""
105+
106+
data: CatalogAgent
107+
108+
@staticmethod
109+
def client_class() -> type[JsonApiAgentPatchDocument]:
110+
return JsonApiAgentPatchDocument

packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/service.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020

2121
from gooddata_sdk import CatalogDeclarativeExportTemplate, CatalogExportTemplate
2222
from gooddata_sdk.catalog.catalog_service_base import CatalogServiceBase
23+
from gooddata_sdk.catalog.organization.entity_model.agent import (
24+
CatalogAgent,
25+
CatalogAgentDocument,
26+
CatalogAgentPatchDocument,
27+
)
2328
from gooddata_sdk.catalog.organization.entity_model.directive import CatalogCspDirective
2429
from gooddata_sdk.catalog.organization.entity_model.identity_provider import CatalogIdentityProvider
2530
from gooddata_sdk.catalog.organization.entity_model.jwk import CatalogJwk, CatalogJwkDocument
@@ -584,6 +589,103 @@ def delete_llm_provider(self, id: str) -> None:
584589
"""
585590
self._entities_api.delete_entity_llm_providers(id, _check_return_type=False)
586591

592+
# Agent APIs
593+
594+
def get_agent(self, id: str) -> CatalogAgent:
595+
"""Get an AI agent by ID.
596+
597+
Args:
598+
id: Agent identifier
599+
600+
Returns:
601+
CatalogAgent: Retrieved agent
602+
"""
603+
response = self._ai_agents_api.get_entity_agents(id, _check_return_type=False)
604+
return CatalogAgent.from_api(response.data)
605+
606+
def list_agents(
607+
self,
608+
filter: str | None = None,
609+
page: int | None = None,
610+
size: int | None = None,
611+
sort: list[str] | None = None,
612+
) -> list[CatalogAgent]:
613+
"""List all AI agents.
614+
615+
Args:
616+
filter: Optional filter string
617+
page: Zero-based page index (0..N)
618+
size: The size of the page to be returned
619+
sort: Sorting criteria in the format: property,(asc|desc).
620+
621+
Returns:
622+
list[CatalogAgent]: List of agents
623+
"""
624+
kwargs: dict[str, Any] = {}
625+
if filter is not None:
626+
kwargs["filter"] = filter
627+
if page is not None:
628+
kwargs["page"] = page
629+
if size is not None:
630+
kwargs["size"] = size
631+
if sort is not None:
632+
kwargs["sort"] = sort
633+
kwargs["_check_return_type"] = False
634+
635+
response = self._ai_agents_api.get_all_entities_agents(**kwargs)
636+
return [CatalogAgent.from_api(agent) for agent in response.data]
637+
638+
def create_agent(self, agent: CatalogAgent) -> CatalogAgent:
639+
"""Create a new AI agent.
640+
641+
Args:
642+
agent: Agent object to create
643+
644+
Returns:
645+
CatalogAgent: Created agent
646+
"""
647+
agent_document = CatalogAgentDocument(data=agent)
648+
response = self._ai_agents_api.create_entity_agents(
649+
json_api_agent_in_document=agent_document.to_api(), _check_return_type=False
650+
)
651+
return CatalogAgent.from_api(response.data)
652+
653+
def update_agent(self, agent: CatalogAgent) -> CatalogAgent:
654+
"""Update an existing AI agent using PUT semantics.
655+
656+
Args:
657+
agent: Agent object with updated values
658+
659+
Returns:
660+
CatalogAgent: Updated agent
661+
"""
662+
agent_document = CatalogAgentDocument(data=agent)
663+
response = self._ai_agents_api.update_entity_agents(agent.id, agent_document.to_api(), _check_return_type=False)
664+
return CatalogAgent.from_api(response.data)
665+
666+
def patch_agent(self, agent: CatalogAgent) -> CatalogAgent:
667+
"""Patch an existing AI agent using PATCH semantics.
668+
669+
Args:
670+
agent: Agent object with fields to patch
671+
672+
Returns:
673+
CatalogAgent: Updated agent
674+
"""
675+
agent_patch_document = CatalogAgentPatchDocument(data=agent)
676+
response = self._ai_agents_api.patch_entity_agents(
677+
agent.id, agent_patch_document.to_api(), _check_return_type=False
678+
)
679+
return CatalogAgent.from_api(response.data)
680+
681+
def delete_agent(self, id: str) -> None:
682+
"""Delete an AI agent.
683+
684+
Args:
685+
id: Agent identifier
686+
"""
687+
self._ai_agents_api.delete_entity_agents(id, _check_return_type=False)
688+
587689
# Layout APIs
588690

589691
def get_declarative_notification_channels(self) -> list[CatalogDeclarativeNotificationChannel]:

packages/gooddata-sdk/src/gooddata_sdk/client.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import gooddata_api_client as api_client
99
import requests
1010
from gooddata_api_client import apis
11+
from gooddata_api_client.api.ai_agents_api import AIAgentsApi
1112

1213
from gooddata_sdk import __version__
1314
from gooddata_sdk.utils import HttpMethod
@@ -71,6 +72,7 @@ def __init__(
7172
self._actions_api = apis.ActionsApi(self._api_client)
7273
self._user_management_api = apis.UserManagementApi(self._api_client)
7374
self._appearance_api = apis.AppearanceApi(self._api_client)
75+
self._ai_agents_api = AIAgentsApi(self._api_client)
7476
self._executions_cancellable = executions_cancellable
7577

7678
def _do_post_request(
@@ -158,6 +160,10 @@ def user_management_api(self) -> apis.UserManagementApi:
158160
def appearance_api(self) -> apis.AppearanceApi:
159161
return self._appearance_api
160162

163+
@property
164+
def ai_agents_api(self) -> AIAgentsApi:
165+
return self._ai_agents_api
166+
161167
@property
162168
def executions_cancellable(self) -> bool:
163169
return self._executions_cancellable

0 commit comments

Comments
 (0)